具有基於地址的授權操作的智能合約
我想建構一個服務,使用者可以在其中註冊(鏈下)以獲取憑據,使他們有權執行某些鏈上操作。
例如,假設我正在建構一項服務,其中有人可以通過持有我的代幣(並燒掉它,或花費它或其他任何東西)來購買我的時間,但我只希望認識我的人能夠購買代幣。所以我有一個網站,我的朋友可以給我他們的地址,然後我的代幣交易將被限制在這些地址內。
我希望這個有效所有者列表是可更新的。我怎樣才能做到這一點?
對於獎勵積分,讓我們假設白名單的變化相對頻繁。頻繁地改變契約變得昂貴。有沒有辦法更新契約本身?
您可以使用帶有修飾符的智能合約,
onlyAgent
其工作方式與onlyOwner
(Ownable) 相同。必須通過使用該addAgent
方法添加代理來批准代理。你的合約必須繼承
AgentRole
https://gist.github.com/Aboudjem/5c3dac7f227ad722791c5d9d14fdb84d
因此,您需要編寫自己的“Oracle”。您的鏈下應用程序可以收集地址,並且只有您有權訪問的管理後端可用於呼叫
registerOwners
契約中的函式,將地址添加到所有者列表中(確保提供一種同時停用它們的方法, 如果需要的話)。這應該被測試,但為了節省燃料,你可以讓你的朋友呼叫一個函式,將他們的地址保存在映射中(一種預註冊),你只需呼叫一個函式來翻轉 a 中的布爾值struct,表示允許預註冊。
2022 年更新
時間流逝,經驗增加;)
您可以使用簽名消息。看看這個契約: https ://etherscan.io/address/0xF2Bce1776A49250A5cad0F81aeb5C21Be72F537a#code
在第 374 行(文件 1,共 21 個):
function mintById_SignedMessage(uint256 _tokenId, uint256 _setPrice, uint256 expirationTimestamp, uint256 _nonce, bytes memory _sig) public payable{ // check validity and execute require(expirationTimestamp <= block.timestamp, "Expired"); bytes32 message = SignedMessages.prefixed(keccak256(abi.encodePacked(msg.sender, _tokenId, _setPrice, expirationTimestamp, _nonce))); require(msg.value == _setPrice, "Wrong payment"); require(SignedMessages.consumePass(message, _sig, _nonce), "Error in signed msg"); _internalMintById(msg.sender, _tokenId); if (msg.value > 0) { emit FundsReceived(msg.sender, msg.value, "payment by minting sale"); } }
通過傳遞所謂的“鑄幣通行證”來呼叫此函式。前往第 3 個文件,共 21 個文件:這是檢查簽名的契約。因此,呼叫參數使用有效的“發行者”鏈下(由您)的私鑰進行簽名。然後你將這個簽名消息提供給使用者(例如通過前端或後端),當他們呼叫合約時,他們可以提供那個簽名消息。你的合約可以驗證它是由正確的發行者發行的,如下所示:
function consumePass(bytes32 message, bytes memory sig, uint256 nonce) internal returns(bool){ // check the nonce first if (nonces[nonce]) { return false; } // check the issuer if (!issuers[recoverSigner(message, sig)]) { return false; } // consume the nonce if it is safe nonces[nonce] = true; return true; }
一些進一步的連結: