如何僅使用合約而不是 Dapp 前端從 DSR(Oasis Saving Dapp / MakerDao)中提取 DAI?
我目前正在測試 MakerDao 的 Oasis Saving Dapp ( https://oasis.app/save )。將部分 DAI 轉換為 DSR 後,使用者可以節省資金,並隨時使用 Dapp 前端提款按鈕提取資金(轉換回 DAI)。
我喜歡這個想法,但在發送更多 DAI 之前,我想弄清楚如何在不使用前端的情況下與合約進行互動。
**有人可以告訴我如何僅使用契約程式碼提取所有儲蓄嗎?**所以不使用 Oasis 前端。我想知道我需要呼叫哪些函式以及要填充什麼作為輸入。
這是部署在儲戶賬戶上的合約程式碼:
pragma solidity ^0.4.23; contract DSAuthority { function canCall( address src, address dst, bytes4 sig ) public view returns (bool); } contract DSAuthEvents { event LogSetAuthority (address indexed authority); event LogSetOwner (address indexed owner); } contract DSAuth is DSAuthEvents { DSAuthority public authority; address public owner; constructor() public { owner = msg.sender; emit LogSetOwner(msg.sender); } function setOwner(address owner_) public auth { owner = owner_; emit LogSetOwner(owner); } function setAuthority(DSAuthority authority_) public auth { authority = authority_; emit LogSetAuthority(authority); } modifier auth { require(isAuthorized(msg.sender, msg.sig)); _; } function isAuthorized(address src, bytes4 sig) internal view returns (bool) { if (src == address(this)) { return true; } else if (src == owner) { return true; } else if (authority == DSAuthority(0)) { return false; } else { return authority.canCall(src, this, sig); } } } contract DSNote { event LogNote( bytes4 indexed sig, address indexed guy, bytes32 indexed foo, bytes32 indexed bar, uint wad, bytes fax ) anonymous; modifier note { bytes32 foo; bytes32 bar; assembly { foo := calldataload(4) bar := calldataload(36) } emit LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data); _; } } // DSProxy // Allows code execution using a persistant identity This can be very // useful to execute a sequence of atomic actions. Since the owner of // the proxy can be changed, this allows for dynamic ownership models // i.e. a multisig contract DSProxy is DSAuth, DSNote { DSProxyCache public cache; // global cache for contracts constructor(address _cacheAddr) public { require(setCache(_cacheAddr)); } function() public payable { } // use the proxy to execute calldata _data on contract _code function execute(bytes _code, bytes _data) public payable returns (address target, bytes32 response) { target = cache.read(_code); if (target == 0x0) { // deploy contract & store its address in cache target = cache.write(_code); } response = execute(target, _data); } function execute(address _target, bytes _data) public auth note payable returns (bytes32 response) { require(_target != 0x0); // call contract in current context assembly { let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 32) response := mload(0) // load delegatecall output switch iszero(succeeded) case 1 { // throw if delegatecall failed revert(0, 0) } } } //set new cache function setCache(address _cacheAddr) public auth note returns (bool) { require(_cacheAddr != 0x0); // invalid cache address cache = DSProxyCache(_cacheAddr); // overwrite cache return true; } } // DSProxyFactory // This factory deploys new proxy instances through build() // Deployed proxy addresses are logged contract DSProxyFactory { event Created(address indexed sender, address indexed owner, address proxy, address cache); mapping(address=>bool) public isProxy; DSProxyCache public cache = new DSProxyCache(); // deploys a new proxy instance // sets owner of proxy to caller function build() public returns (DSProxy proxy) { proxy = build(msg.sender); } // deploys a new proxy instance // sets custom owner of proxy function build(address owner) public returns (DSProxy proxy) { proxy = new DSProxy(cache); emit Created(msg.sender, owner, address(proxy), address(cache)); proxy.setOwner(owner); isProxy[proxy] = true; } } // DSProxyCache // This global cache stores addresses of contracts previously deployed // by a proxy. This saves gas from repeat deployment of the same // contracts and eliminates blockchain bloat. // By default, all proxies deployed from the same factory store // contracts in the same cache. The cache a proxy instance uses can be // changed. The cache uses the sha3 hash of a contract's bytecode to // lookup the address contract DSProxyCache { mapping(bytes32 => address) cache; function read(bytes _code) public view returns (address) { bytes32 hash = keccak256(_code); return cache[hash]; } function write(bytes _code) public returns (address target) { assembly { target := create(0, add(_code, 0x20), mload(_code)) switch iszero(extcodesize(target)) case 1 { // throw if contract failed to deploy revert(0, 0) } } bytes32 hash = keccak256(_code); cache[hash] = target; } }
來源:https ://etherscan.io/address/0xad01c274961a55a493991e1f63e0c362aabf6705#code
點擊 Dapp 上的撤消按鈕時,似乎
execute()
呼叫了該函式,但我不明白什麼是bytes _data
. Metamask 為這個參數顯示了一個很長的輸入(228 字節),但我不明白它的含義以及如何在需要時自己猜測它。有人知道要準確呼叫什麼以及要填寫什麼作為輸入嗎?作為一個去中心化的應用程序,如果由於某種原因前端不可用(維護、更新……)並且有人想要他的資金回來,這將非常有用。
謝謝 :)
但我不明白是什麼
bytes _data
這是一個編碼的函式呼叫,在 function 內部執行(通過彙編)
execute
。以下是編碼函式呼叫的範例:
bytes4 selector = bytes4(uint256(keccak256("someFunc(address,uint256,bool)") >> 224)); bytes memory data = abi.encodeWithSelector(selector, someAddress, someUint256, someBool);
當然,上面的編碼是在鏈上(合約內部)執行的,而您需要在鏈下(例如,在 web3.js 腳本中)計算相同的東西,然後將其傳遞給合約的功能。
萬一綠洲網站消失了怎麼辦?我的代幣是否因為被委派了一份困難的契約而面臨風險?
這就是為什麼我也想知道如何僅使用契約程式碼提取我的儲蓄。
從上面的答案看起來很複雜,我不知道如何生成該數據欄位。也許有人可以對MEW合約互動進行逐步描述以退出綠洲DSR合約嗎?