Skip to content

Commit

Permalink
Updated contracts and README
Browse files Browse the repository at this point in the history
  • Loading branch information
ayobuenavista committed Aug 1, 2019
1 parent 3420efb commit e4a94e8
Show file tree
Hide file tree
Showing 8 changed files with 1,435 additions and 29 deletions.
8 changes: 2 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -640,10 +640,6 @@ With Ganache running, execute:
truffle migrate --network development --reset
```

## Workshop Exercises
## Hackathon Bounties

#### 1. Create a smart contract that splits ETH into 3 different tokens. In the constructor, specify the 3 different tokens and percentage distribution of each token.

#### 2. Launch an Automated Price Reserve with your own custom token.

#### 3. Integrate token swaps in your own solidity project.
For our hackathon bounties, please visit https://kyber.network/hack.
84 changes: 61 additions & 23 deletions contracts/ExpectedRate.sol
Original file line number Diff line number Diff line change
Expand Up @@ -55,27 +55,10 @@ contract ExpectedRate is Withdrawable, ExpectedRateInterface, Utils2 {

if (srcQty == 0) srcQty = 1;

uint bestReserve;
uint worstCaseSlippageRate;
bool didRevert = false;

if (usePermissionless) {
(bestReserve, expectedRate) = kyberNetwork.findBestRate(src, dest, srcQty);

if (quantityFactor != 1) {
(bestReserve, slippageRate) = kyberNetwork.findBestRate(src, dest, (srcQty * quantityFactor));
} else {
slippageRate = expectedRate;
}
} else {
(bestReserve, expectedRate) = kyberNetwork.findBestRateOnlyPermission(src, dest, srcQty);

if (quantityFactor != 1) {
(bestReserve, slippageRate) = kyberNetwork.findBestRateOnlyPermission(src, dest,
(srcQty * quantityFactor));
} else {
slippageRate = expectedRate;
}
}
(didRevert, expectedRate, slippageRate) = safeFindBestRate(src, dest, srcQty, usePermissionless);
if (didRevert) return (0, 0);

if (expectedRate == 0) {
expectedRate = expectedRateSmallQty(src, dest, srcQty, usePermissionless);
Expand All @@ -88,9 +71,9 @@ contract ExpectedRate is Withdrawable, ExpectedRateInterface, Utils2 {
if (checkKncArbitrageRate(expectedRate)) expectedRate = 0;
}

require(expectedRate <= MAX_RATE);
if (expectedRate > MAX_RATE) return (0, 0);

worstCaseSlippageRate = ((10000 - worstCaseRateFactorInBps) * expectedRate) / 10000;
uint worstCaseSlippageRate = ((10000 - worstCaseRateFactorInBps) * expectedRate) / 10000;
if (slippageRate >= worstCaseSlippageRate) {
slippageRate = worstCaseSlippageRate;
}
Expand All @@ -101,7 +84,11 @@ contract ExpectedRate is Withdrawable, ExpectedRateInterface, Utils2 {
function checkKncArbitrageRate(uint currentKncToEthRate) public view returns(bool) {
uint converseRate;
uint slippage;
(converseRate, slippage) = getExpectedRate(ETH_TOKEN_ADDRESS, knc, UNIT_QTY_FOR_FEE_BURNER, true);
(converseRate, slippage) = getExpectedRate(ETH_TOKEN_ADDRESS, knc, UNIT_QTY_FOR_FEE_BURNER, true);

// if returned rate is 0, can't trust this arb test. assume we have arb
if(converseRate == 0) return true;

require(converseRate <= MAX_RATE && currentKncToEthRate <= MAX_RATE);
return ((converseRate * currentKncToEthRate) > (PRECISION ** 2));
}
Expand All @@ -121,4 +108,55 @@ contract ExpectedRate is Withdrawable, ExpectedRateInterface, Utils2 {
(reserve, rateEthToDest) = kyberNetwork.searchBestRate(ETH_TOKEN_ADDRESS, dest, ethQty, usePermissionless);
return rateSrcToEth * rateEthToDest / PRECISION;
}

function safeFindBestRate(ERC20 src, ERC20 dest, uint srcQty, bool usePermissionless)
internal view
returns (bool didRevert, uint expectedRate, uint slippageRate)
{
bytes4 sig = usePermissionless ?
bytes4(keccak256("findBestRate(address,address,uint256)")) :
bytes4(keccak256("findBestRateOnlyPermission(address,address,uint256)")); //Function signatures

(didRevert, expectedRate) = assemblyFindBestRate(src, dest, srcQty, sig);

if (didRevert) return (true, 0, 0);

if (quantityFactor != 1) {
(didRevert, slippageRate) = assemblyFindBestRate(src, dest, (srcQty * quantityFactor), sig);
} else {
slippageRate = expectedRate;
}
}

function assemblyFindBestRate(ERC20 src, ERC20 dest, uint srcQty, bytes4 sig)
internal view
returns (bool didRevert, uint rate)
{
address addr = address(kyberNetwork); // kyber address
uint success;

assembly {
let x := mload(0x40) // "free memory pointer"
mstore(x,sig) // function signature
mstore(add(x,0x04),src) // src address padded to 32 bytes
mstore(add(x,0x24),dest) // dest padded to 32 bytes
mstore(add(x,0x44),srcQty) // uint 32 bytes
mstore(0x40,add(x,0xa4)) // set free storage pointer to empty space after output

// input size = sig + ERC20 (address) + ERC20 + uint
// = 4 + 32 + 32 + 32 = 100 = 0x64
success := staticcall(
gas, // gas
addr, // Kyber addr
x, // Inputs at location x
0x64, // Inputs size bytes
add(x, 0x64), // output storage after input
0x40) // Output size are (uint, uint) = 64 bytes

rate := mload(add(x,0x84)) //Assign 2nd output to rate, first output not used,
mstore(0x40,x) // Set empty storage pointer back to start position
}

if (success != 1) didRevert = true;
}
}
Loading

0 comments on commit e4a94e8

Please sign in to comment.