Skip to content

Instantly share code, notes, and snippets.

@samczsun
Created September 30, 2019 03:45
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save samczsun/c20119b80f6f7f0a8e197666e0a2b1c9 to your computer and use it in GitHub Desktop.
Save samczsun/c20119b80f6f7f0a8e197666e0a2b1c9 to your computer and use it in GitHub Desktop.
Ethereum Scripts
contract BZxOracleLike {
}
contract BZxLike {
function orders(bytes32) public view returns (address, address, address, address, uint, uint, uint, uint, uint, bytes32);
function getRequiredCollateral(ERC20Like,ERC20Like,BZxOracleLike,uint256,uint256) public returns (uint);
}
contract BZxLoanTokenBase {
function borrowInterestRate() public view returns (uint);
function nextBorrowInterestRate(uint) public view returns (uint);
function loanOrderHashes(uint) public view returns (bytes32);
function marketLiquidity() public view returns (uint);
}
contract BZxLoanTokenV2Like is BZxLoanTokenBase {
function borrowTokenAndUse(
uint256 borrowAmount,
uint256 leverageAmount,
uint256 interestInitialAmount,
uint256 loanTokenSent,
uint256 collateralTokenSent,
uint256 tradeTokenSent,
address borrower,
address collateralTokenAddress,
address tradeTokenAddress
) public returns (bytes32);
}
contract BZxLoanTokenV3Like is BZxLoanTokenBase {
function borrowTokenAndUse(
uint256 borrowAmount,
uint256 leverageAmount,
uint256 interestInitialAmount,
uint256 loanTokenSent,
uint256 collateralTokenSent,
uint256 tradeTokenSent,
address borrower,
address collateralTokenAddress,
address tradeTokenAddress,
bytes memory
) public returns (bytes32);
}
contract BZxHelpers is Logger, Constants, TokenHelper {
BZxLike private constant BZX = BZxLike(0x1Cf226E9413AddaF22412A2E182F9C0dE44AF002);
BZxOracleLike private constant BZX_ORACLE = BZxOracleLike(0xF257246627f7CB036AE40Aa6cFe8D8CE5F0EbA63);
uint private constant LEVERAGE_AMOUNT = 2000000000000000028;
function getLoanParameters(BZxLoanTokenBase loanToken, uint leverageAmount, uint amountToBorrow) internal view returns (uint, uint, uint) {
bytes32 loanOrderHash = loanToken.loanOrderHashes(leverageAmount);
(,,,,uint loanOrderAmount, uint interestAmount, uint initialMarginAmount,, uint maxDurationUnixTimestampSec,) = BZX.orders(loanOrderHash);
uint newInterestRate = loanToken.nextBorrowInterestRate(amountToBorrow);
loanOrderAmount = loanOrderAmount + amountToBorrow;
interestAmount = loanOrderAmount * newInterestRate / 365 / 10**20;
uint owedPerDay = amountToBorrow * interestAmount / loanOrderAmount;
return (maxDurationUnixTimestampSec, owedPerDay, initialMarginAmount);
}
function doBorrow(BZxLoanTokenBase loanToken, bool v3, uint amountToBorrow, ERC20Like interest, ERC20Like collateral) internal returns (bytes32) {
(uint maxDurationUnixTimestampSec, uint owedPerDay, uint initialMarginAmount) = getLoanParameters(loanToken, LEVERAGE_AMOUNT, amountToBorrow);
uint interestAmountRequired = maxDurationUnixTimestampSec * owedPerDay / 86400;
uint collateralRequired = BZX.getRequiredCollateral(
interest,
collateral,
BZX_ORACLE,
amountToBorrow,
initialMarginAmount
);
collateralRequired = collateralRequired + collateralRequired * 10**20 / initialMarginAmount;
printf("collateral_required=%s, interest_required=%s\n", abi.encode(stringify(collateralRequired, collateral.decimals()), stringify(interestAmountRequired, interest.decimals())));
if (interest.balanceOf(address(this)) < interestAmountRequired) borrowInterest(interestAmountRequired - interest.balanceOf(address(this)));
if (collateral.balanceOf(address(this)) < interestAmountRequired) borrowCollateral(collateralRequired - collateral.balanceOf(address(this)));
interest.approve(address(loanToken), interestAmountRequired);
collateral.approve(address(loanToken), collateralRequired);
if (v3) {
return BZxLoanTokenV3Like(address(loanToken)).borrowTokenAndUse(
amountToBorrow,
LEVERAGE_AMOUNT,
0,
interestAmountRequired,
collateralRequired,
0,
address(this),
address(collateral),
address(0),
""
);
} else {
return BZxLoanTokenV2Like(address(loanToken)).borrowTokenAndUse(
amountToBorrow,
LEVERAGE_AMOUNT,
0,
interestAmountRequired,
collateralRequired,
0,
address(this),
address(collateral),
address(0)
);
}
}
function borrowInterest(uint amount) internal {}
function borrowCollateral(uint amount) internal {}
}
pragma solidity ^0.5.11;
import "./Interfaces.sol";
contract Constants {
ERC20Like internal constant KYBER_ETH = ERC20Like(0x00eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee);
ERC20Like internal constant KNC = ERC20Like(0xdd974D5C2e2928deA5F71b9825b8b646686BD200);
ERC20Like internal constant DAI = ERC20Like(0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359);
ERC20Like internal constant USDT = ERC20Like(0xdAC17F958D2ee523a2206206994597C13D831ec7);
ERC20Like internal constant USDC = ERC20Like(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
ERC20Like internal constant REP = ERC20Like(0x1985365e9f78359a9B6AD760e32412f4a445E862);
ERC20Like internal constant WBTC = ERC20Like(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599);
ERC20Like internal constant BAT = ERC20Like(0x0D8775F648430679A709E98d2b0Cb6250d2887EF);
WETHLike internal constant WETH = WETHLike(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
MatchingMarketLike internal constant MATCHING_MARKET = MatchingMarketLike(0x39755357759cE0d7f32dC8dC45414CCa409AE24e);
UniswapFactoryLike internal constant UNISWAP_FACTORY = UniswapFactoryLike(0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95);
KyberNetworkLike internal constant KYBER_NETWORK = KyberNetworkLike(0x9ae49C0d7F8F9EF4B864e004FE86Ac8294E20950);
KyberNetworkLike internal constant KYBER_PROXY = KyberNetworkLike(0x818E6FECD516Ecc3849DAf6845e3EC868087B755);
OrderbookListerLike internal constant ORDERBOOK_LISTER = OrderbookListerLike(0x84AFA106FbF9B45E369724024cae14E8C7529c26);
BancorConverterRegistryLike internal constant BANCOR_REGISTRY = BancorConverterRegistryLike(0x0DDFF327ddF7fE838e3e63d02001ef23ad1EdE8e);
}
contract OracleLike {
function getPrice(ERC20Like asset) public view returns (uint);
}
contract DaiOracleLike is OracleLike {
function updatePrice() public returns (bool);
function peek() public view returns (uint256);
function getEth2DaiPrice() public view returns (uint256);
function getUniswapPrice() public view returns (uint256);
}
contract HydroLike {
enum ActionType {
Deposit,
Withdraw,
Transfer,
Borrow,
Repay,
Supply,
Unsupply
}
struct Action {
ActionType actionType;
bytes encodedParams;
}
enum BalanceCategory {
Common,
CollateralAccount
}
struct BalancePath {
BalanceCategory category;
uint16 marketID;
address user;
}
struct Market {
address baseAsset;
address quoteAsset;
uint256 liquidateRate;
uint256 withdrawRate;
uint256 auctionRatioStart;
uint256 auctionRatioPerBlock;
bool borrowEnable;
}
function batch(Action[] memory) public payable;
function getMarket(uint16) external view returns (Market memory);
function getPoolCashableAmount(ERC20Like asset) external view returns (uint);
}
pragma solidity ^0.5.11;
contract ERC20Like {
function decimals() public returns (uint8);
function name() public returns (string memory);
function symbol() public returns (string memory);
function approve(address,uint) public;
function balanceOf(address) public view returns (uint);
}
contract BancorLike {
function quickConvert(ERC20Like[] memory, uint256, uint256) public payable returns (uint);
function token() public view returns (ERC20Like);
}
contract BancorConverterRegistryLike {
function converterCount(ERC20Like) public view returns (uint);
function converterAddress(ERC20Like, uint32) public view returns (BancorLike);
}
contract UniswapLike {
function ethToTokenSwapOutput(uint, uint) public payable returns (uint);
function tokenToEthSwapInput(uint, uint, uint) public returns (uint);
}
contract UniswapFactoryLike {
function getExchange(ERC20Like) public view returns (UniswapLike);
}
contract KyberNetworkLike {
function getExpectedRate(ERC20Like, ERC20Like, uint) public returns (uint, uint);
function findBestRate(ERC20Like, ERC20Like, uint) public returns (uint, uint);
function tradeWithHint(ERC20Like, uint, ERC20Like, address, uint, uint, address, bytes memory) public payable returns (uint);
}
contract OrderListLike {
function nextFreeId() public view returns (uint32);
}
contract OrderbookReserveLike {
function depositEther(address) public payable;
function depositToken(address, uint) public;
function depositKncForFee(address, uint) public;
function submitEthToTokenOrder(uint128, uint128) public returns (bool);
function cancelEthToTokenOrder(uint32) public returns (bool);
function submitTokenToEthOrder(uint128, uint128) public returns (bool);
function cancelTokenToEthOrder(uint32) public returns (bool);
function withdrawToken(uint) public;
function withdrawEther(uint) public;
function withdrawKncFee(uint) public;
function makerFunds(address, ERC20Like) public view returns (uint);
function makerKnc(address) public view returns (uint);
function calcKncStake(uint) public view returns(uint);
function ethToTokenList() public view returns (OrderListLike);
function tokenToEthList() public view returns (OrderListLike);
}
contract MatchingMarketLike {
function getBuyAmount(ERC20Like,ERC20Like,uint) public returns (uint);
function getPayAmount(ERC20Like,ERC20Like,uint) public returns (uint);
function buyAllAmount(ERC20Like,uint,ERC20Like,uint) public returns (uint);
function sellAllAmount(ERC20Like,uint,ERC20Like,uint) public returns (uint);
function offer(uint,ERC20Like,uint,ERC20Like) public returns (uint);
function insert(uint,uint) public returns (bool);
function cancel(uint) public returns (bool);
}
contract WETHLike is ERC20Like {
function deposit() public payable;
function withdraw(uint) public;
}
contract OrderbookListerLike {
function addOrderbookContract(ERC20Like) public returns (bool);
function initOrderbookContract(ERC20Like) public returns (bool);
function listOrderbookContract(ERC20Like) public returns (bool);
function reserves(ERC20Like) public view returns (OrderbookReserveLike);
}
pragma solidity ^0.5.11;
import "./Step.sol";
// @dev Functions to convert various types into pretty string versions
contract IStringify {
// @dev stringify a uint to base 10
function stringify(uint256 input) internal pure returns (string memory);
// @dev stringify a uint to base 10 with a set amount of decimal places
function stringify(uint256 input, uint256 decimals) internal pure returns (string memory);
// @dev stringify an int to base 10
function stringify(int256 input) internal pure returns (string memory);
// @dev stringify an int to base 10 with a set amount of decimal places
function stringify(int256 input, uint256 decimals) internal pure returns (string memory);
// @dev stringify a bool
function stringify(bool input) internal pure returns (string memory);
// @dev stringify bytes into hex with a 0x prefix
function stringify(bytes memory input) internal pure returns (string memory);
// @dev stringify a bytes32 to a fixed length, truncating the least significant bytes
function stringify(bytes32 input, uint len) internal pure returns (string memory);
// @dev stringify an address, checksummed
function stringify(address input) internal pure returns (string memory);
}
// @dev various string utilities
contract IStringUtils {
// @dev prints a formatted string to the log
// @dev use abi.encode() to construct the args. supported formatting codes are:
// %d for an integer
// %u for an unsigned integer
// %.[n]d for an integer with n decimal places, or unspecified to use the preceding arg
// %.[n]u for an unsigned integer with n decimal places, or unspecified to use the preceding arg
// %a for an address
// %b for a boolean (non-zero values are treated as true)
// %[n]x for a bytes[n] type
// %x for a bytes type
// %s for a string type
// %% to write a percentage sign
function sprintf(string memory formatStr, bytes memory args) internal returns (string memory);
// @dev escapes a string for use in json
function jsonEscape(string memory inputStr) internal pure returns (string memory);
}
// @dev facilitates logging
contract ILogger {
// @dev prints a string to the log
function print(string memory str) internal;
// @dev prints a newline
function println() internal;
// @dev prints a string followed by a newline to the log
function println(string memory str) internal;
// @dev prints a formatted string to the log, see IStringUtils.sprintf
function printf(string memory format, bytes memory args) internal;
}
contract IScript is ILogger {
using Step for Step.Data;
// @dev called at the beginning of script execution
function setup() public {}
// @dev set the name of this script, can only be called during setup
function name(string memory scriptName) internal;
// @dev set the block that this script will run on, can only be called during setup
function blockNumber(uint blockNr) internal;
// @dev called after setup, define steps here
function run() public;
// @dev define a new step with the given description
function begin(string memory desc) internal returns (Step.Data storage);
}
pragma solidity ^0.5.11;
library Step {
// @dev a single call to be made during a step, with an optional short description of what the call will do
struct Call {
string desc;
function() external func;
}
// @dev a step represents a set of calls to specific functions made by the specified caller
// all steps share the same gas and balance
struct Data {
string desc;
address payable caller;
uint balance;
uint gas;
Call[] calls;
}
// @dev set the step's caller, defaults to a random address if unset
function withCaller(Data storage self, address payable caller) internal returns (Data storage) {
self.caller = caller;
return self;
}
// @dev set the amount of ether the step gets, defaults to 0
function withBalance(Data storage self, uint balance) internal returns (Data storage) {
self.balance = balance;
return self;
}
// @dev set the amount of gas the step gets, defaults to the most recent block gas limit
function withGas(Data storage self, uint gas) internal returns (Data storage) {
self.gas = gas;
return self;
}
// @dev add a call to be made during this step
function call(Data storage self, function() external func) internal returns (Data storage) {
return call(self, "", func);
}
// @dev add a call to be made during this step, with a short description
function call(Data storage self, string memory desc, function() external func) internal returns (Data storage) {
self.calls.push(Call({desc: desc, func: func}));
return self;
}
// @notice aliases for call()
function first(Data storage self, function() external func) internal returns (Data storage) { return call(self, func); }
function first(Data storage self, string memory desc, function() external func) internal returns (Data storage) { return call(self, desc, func); }
function before(Data storage self, function() external func) internal returns (Data storage) { return call(self, func); }
function before(Data storage self, string memory desc, function() external func) internal returns (Data storage) { return call(self, desc, func); }
function then(Data storage self, function() external func) internal returns (Data storage) { return call(self, func); }
function then(Data storage self, string memory desc, function() external func) internal returns (Data storage) { return call(self, desc, func); }
function finally(Data storage self, function() external func) internal returns (Data storage) { return call(self, func); }
function finally(Data storage self, string memory desc, function() external func) internal returns (Data storage) { return call(self, desc, func); }
}
pragma solidity ^0.5.11;
import "./Interfaces.sol";
import "./Constants.sol";
library TokenHelperInternal {
UniswapFactoryLike internal constant UNISWAP_FACTORY = UniswapFactoryLike(0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95);
BancorConverterRegistryLike internal constant BANCOR_REGISTRY = BancorConverterRegistryLike(0x0DDFF327ddF7fE838e3e63d02001ef23ad1EdE8e);
function getUniswapExchange(ERC20Like token) internal returns (UniswapLike) {
UniswapLike uniswap = UNISWAP_FACTORY.getExchange(token);
if (uniswap == UniswapLike(0x0)) {
revert(string(abi.encodePacked("error: no uniswap exchange available for ", token.symbol())));
}
return uniswap;
}
function getBancorExchange(ERC20Like token) internal returns (BancorLike) {
uint converterCount = BANCOR_REGISTRY.converterCount(token);
if (converterCount == 0) {
revert(string(abi.encodePacked("error: no bancor converters available for ", token.symbol())));
}
return BANCOR_REGISTRY.converterAddress(token, uint32(converterCount - 1));
}
function getFromBancor(ERC20Like token, uint amount) internal {
BancorLike bancor = getBancorExchange(token);
ERC20Like[] memory path = new ERC20Like[](5);
path[0] = ERC20Like(0xc0829421C1d260BD3cB3E0F06cfE2D52db2cE315);
path[1] = ERC20Like(0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C);
path[2] = ERC20Like(0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C);
path[3] = bancor.token();
path[4] = token;
bancor.quickConvert.value(amount)(path, amount, 1);
}
function giveToBancor(ERC20Like token, uint amount) internal {
if (amount == 0) return;
BancorLike bancor = getBancorExchange(token);
token.approve(address(bancor), amount);
ERC20Like[] memory path = new ERC20Like[](5);
path[0] = token;
path[1] = bancor.token();
path[2] = ERC20Like(0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C);
path[3] = ERC20Like(0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C);
path[4] = ERC20Like(0xc0829421C1d260BD3cB3E0F06cfE2D52db2cE315);
bancor.quickConvert(path, amount, 1);
}
function giveAllToBancor(ERC20Like token) internal {
giveToBancor(token, token.balanceOf(address(this)));
}
function getFromUniswap(ERC20Like token, uint amount) internal {
getFromUniswap(token, getUniswapExchange(token), amount);
}
function getFromUniswap(ERC20Like token, UniswapLike uniswap, uint amount) internal {
uniswap.ethToTokenSwapOutput.value(address(this).balance)(amount, uint(-1));
}
function giveToUniswap(ERC20Like token, uint amount) internal {
if (amount == 0) return;
UniswapLike uniswap = getUniswapExchange(token);
token.approve(address(uniswap), amount);
uniswap.tokenToEthSwapInput(amount, 1, uint(-1));
}
function giveAllToUniswap(ERC20Like token) internal {
giveToUniswap(token, token.balanceOf(address(this)));
}
function approveBalance(ERC20Like token, address who) internal {
token.approve(who, token.balanceOf(address(this)));
}
}
library WETHHelperInternal {
function depositAll(WETHLike weth, uint amount) internal {
weth.deposit.value(amount)();
}
function withdrawAll(WETHLike weth) internal {
weth.withdraw(weth.balanceOf(address(this)));
}
}
contract TokenHelper is Constants {
using TokenHelperInternal for ERC20Like;
using WETHHelperInternal for WETHLike;
}
@apocys
Copy link

apocys commented Feb 20, 2020

Thanks for your work, can you also post the code of Script.sol?

Great. Were you able to access the missing code pieces ?

@DiveInto
Copy link

Thanks for your work, can you also post the code of Script.sol?

Great. Were you able to access the missing code pieces ?

nope

@dryruner
Copy link

Can you please also post Script.sol for education purpose? Thanks : )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment