Inspiration
Is really having a user friendly interface that is profitable to the users pocketbook that is transparent with the web3 with security features that feature best practice.
What it does
We worked together to plan out and create a DEX exchange system application. Where the client user will use our browser connected wallet to secure web3 crypto funding, balance inquiry, and exchange of coins. What makes us better than the other wallets on the market is that our wallet/ contracts not only allow you to purchase crypto and grow interest of crypto, but allows for some of the possible risk from possible crypto coin choice depreciation to be mitigated by allowing the depreciation to be exchanged into another cryptocurrency coin when the client requests. The contract allows for a minimum time period for the wallet investment to grow by said secure web3 contract. Under the 'contracts' folder, you can see the use of solidity language used in the interface with where we use best practices for most secure protocol. Test aggregator is used to test the other contracts ability to read data from another aggregator contract.
How we built it
boldFunctionality and Non-Functional Requirements:
Chainlink price feeds, Brownie, Etherscan and Metamask were used as well as Goerli Testnet were all used.
Lending.sol Contract:
The application uses ID to identify the client user and maps to the address (URL)
of the borrower. From there the client is taken through the DEX wallet function
to acquire wanted coin and sign up for the contract services with minimal liability on the
client user than that of a traditional banking loan or credit card. The client must agree to the
the time and fee if early termination of contract is requested by the client.
The application checks the client's funds for funding the contract.
The struct loan has all the variables for the loan function: loan i, borrower, interest rate, collateral Amount,
Collateral amount USD, loan amount, loan starting time, loan duration, loan ending time, and loan state.
IERC20 USD token and link token are used. The Loan state enumerates none, borrowed, repaid or failed.
Our constructor maps addresses to the tokens and price feeds.
'borrow' function is called when button is clicked to get the loan.
The function then checks the applicant's collateral amount to qualify for services.
If the applicant qualifies with enough collateral, then the LINKtoken calls transfer form loan.borrower address(this)
loan.collateralAmount. Else, "not enough collateral will show up on the page and the transfer will fail.
'loans' array maps the ID to the 4 functions collateral amount, collateralAmountUSDT, interestRate and loanEnding Time.
Interest rate is set based on when the client applicant qualifies and can fluctuate based on the volatility of the crypto exchange markets and specified coin request.
Deposit function is called to make initial and client requested additional deposits when client requests.
Modifier checks the status of loan repayment.
Staking.sol:
abstract Contract Context:
Uses the msg.sender and msg.data in our meta transaction process.
The contract module provides a basic control mechanism where the account owner is granted exclusive access to specific functionality of the application.
Inheritance is used when there is a transfer of ownership, disallowing any new owner to access the original owner's private data.
Constructor sets the _msg.sender as the owner and modifier onlyOwner secures the account is
someone other than the owner tries to access an account.
If the wants to cancel, the renounceOwnership function sets the _setOwner address to 0 and that deletes the address location setting the old address to 0.
ReentrancyGaurd:
ReentrancyGaurd protects the authenticity of the data being sent, making sure that there are no nested reentry calls attempted to them.
Disallowing calling to each other, making the data private and using external modifier to access reentry points to the functions.
To keep gas cost as low as possible Boolean are not used instead best practices use uint256 which writes back preventing defending against
contract upgrade attacks and a pointer aliasing. This security cannot be disabled.
The values of our constants _NOT_ENTERED =1, _ENTERED = 2 amke deployment a little higher but in turn makes the
every call to nonreentrant lower amount amking a full refund more likely.
modifier nonReentrant()
Prevents a contract from calling itself, directly or indirectly.
* Calling a nonReentrant function from another nonReentrant
* function is not supported. It is possible to prevent this from happening
* by making the nonReentrant function external, and make it call a
* private function that does the actual work.
Moves amount tokens from the caller's account to recipient
* Returns a boolean value indicating whether the operation succeeded.
* Emits a {Transfer} event
Returns the remaining number of tokens that spender will be
* allowed to spend on behalf of owner through {transferFrom}. This is
* zero by default
* This value changes when {approve} or {transferFrom} are called
Sets amount as the allowance of spender over the caller's tokens.
* Returns a boolean value indicating whether the operation succeeded.
*Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
* Emits an {Approval} event.
Owner set allowances of spender for an owner calls to {approve} with the 'value'
being the new allowance.
library Address:
Returns true if account is a contract.
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
* Among others, isContract will return false for the following
* types of addresses:
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
function isContract(address account) internal view returns (bool)
This method relies on extcodesize, which returns 0 for contracts in
construction, since the code is only stored at the end of the
constructor execution.
Replacement for Solidity's transfer: sends amount wei to
* recipient, forwarding all available gas and reverting on errors.
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by transfer, making them unable to receive funds via
* transfer. {sendValue} removes this limitation.
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
* IMPORTANT: because control is transferred to recipient, care must be
* taken to not create reentrancy vulnerabilities.
function functionCall(address target, bytes memory data)
Performs a Solidity function call using a low level call. A
* plain call is an unsafe replacement for a function call: use this
* function instead.
* If target reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
* Requirements:
* - target must be a contract.
* - calling target with data must not revert.
function functionCallWithValue
Same as {xref-Address-functionCall-address-bytes-}[functionCall],
* but also transferring value wei to target.
* Requirements:
* - the calling contract must have an ETH balance of at least value.
* - the called Solidity function must be payable
function functionStaticCall
Same as {xref-Address-functionCall-address-bytes-}[functionCall],
* but performing a static call.
library SafeERC20
Wrappers around ERC20 operations that throw on failure (when the token
- contract returns false). Tokens that return no value (and instead revert or
- throw on failure) are also supported, non-reverting calls are assumed to be
- successful.
- To use this library you can add a
using SafeERC20 for IERC20;statement to your contract, - which allows you to call the safe operations as
token.safeTransfer(...), etc.
function safeApprove safeApprove should only be called when setting an initial allowance, or when resetting it to zero. To increase and decrease it, use 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
function _callOptionalReturn(IERC20 token, bytes memory data) private We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that the target address contains contract code and also asserts for success in the low-level call. The aggregator Interface contains 3 functions decimals, description, and version. Three functions are getRoundData and latestRoundData should both raise "No data present" if they do not have data to report, instead of returning unset values which could be misinterpreted as actual reported values. Stake memory stake writes the blocks time stamp for staking usage, claiming your staking rewards. The index of the stakes time stamps are used to claim intrest or depresation on claimed stakes. If the msg.sender locktie + extra time < block.timestamp the function returns false. Other wise the total reward is calcualted appropriatly.
There is a small fee if the time lock duration is not met by the client user. function _calculationOfTheAmountOfInterest is calculated with the APR for the stake amount , duration and locks the apr.
function _tokenCalculationToCoverDepreciation
uses a if else statement where ''' if (_initialPrice < _finalPrice) { depreciation = 0; } else { depreciation = (_stakeAmount * (_initialPrice - _finalPrice)) / _finalPrice; }'''
Returning the depreciation of the claimed stake.
This is where the depreciation is then transferred into an alternative coin with the function _tokensToPay. The gas for the depreciation reward gas is funded by a fee to the user when initiated
Challenges we ran into
We overcame many challenges as a team working together. Our team has all levels of developers leaning while competing from across the globe. We overcame the time differences by making time to do a first actual video call to get started and worked together via chat afterwards to smooth over some of the beginner challenges. For example, I have never done a full stack before so when I got the correct contracts 2 days before the deadline the team stepped up to compensate for where my previous knowledge ended and learning began. We helped each other instead of blaming each other, fixing the issues together while creating a healthy learning experience for all. We broke cultural barriers that divide and instead used a common interest to come together to overcome and learn together.
Accomplishments that we're proud of
We are proud to be able to operate a financial system in Turkey on the blockchain with the currency protected deposit we have made. We are also happy that we have been able to build a system that does not require intermediaries and trusts, and that we have been able to bring the equivalent of an application in classical finance to the blockchain.
What we learned
We learned what it means to work together as a team. We grew from that uncomfortable feeling of getting things wrong and listening to others on ways to fix those problems. First of all, it should be noted that we have crossed a very important threshold by performing our first hackathon experience. We are excited to be more experienced and organized in the next competitions and events. In the development part, we have made progress in many areas such as being able to develop a dapp and trying to do this, writing contracts, connecting to the web3, testing the application. We also gained a better understanding of how Chainlink Price Feeds work and their importance for decentralization. Finally, we learned how a lending application works, how the "currency protected deposit" system, the only example in the world in Turkey, works and how we can explain all this to EVM through codes, by researching and applying.
What's next for Currency Protected Deposit
To build out the scope of the project to global scale beyond the Turkish borders.
Built With
- alchemyapi
- brownie
- chainlink
- css
- etherscan
- goerli
- html
- javascript
- metamask
- python
- remix
- solidity
- svelte
Log in or sign up for Devpost to join the conversation.