Erc-20
ERC20 錢包的通用 Gas 錢包?
我們有一個錢包結構,使用者將代幣發送到為他們生成的個人使用者錢包地址,然後我們將使用者錢包中的所有資金清掃到一個集中的池中。個人錢包充當使用者資金的接收地址。通常,當發生 ETH 轉賬時,交易費用從資金中扣除,我們承擔費用。
當發生 ERC20 代幣存款時,我們現在必須將 ETH 發送到該地址以支付掃描的交易成本。這遠不是一個好的解決方案(它留下了事務更改並且難以實施)
天真的解決方案:每次我檢測到一個 ERC20 存入該錢包時,只需將 ETH 發送到使用者的錢包中,這樣該錢包就可以支付用於轉移的氣體。
地址工廠契約:受此答案的啟發,創建了一個將為契約生成地址的契約。不足之處是每個地址生成的氣體。
看起來 Meta Transactions 是解決這個問題的一種方式,相關連結。
我們的特殊限制:
- 使用地址作為標識
- 最小的使用者體驗權衡
解決方案:生成接收者合約的合約
接收方地址生成合約:
contract Factory { address public owner; mapping ( uint256 => address ) public receiversMap; uint256 public receiverCount = 0; constructor() public { /* Deployer's address ( Factory in our case ) do not pass this as a constructor argument because etherscan will have issues displaying our validated source code */ owner = msg.sender; } /* @notice Transfer Ownership of this contract to another address @param newOwner - Address of the next Owner of the contract */ function transferOwner(address newOwner) public { require (msg.sender == owner); owner = newOwner; } /* @notice Create a number of receiver contracts @param number - 0-255 */ function createReceivers( uint8 number ) public { require(msg.sender == owner); for(uint8 i = 0; i < number; i++) { // Create and index our new receiver receiversMap[++receiverCount] = new Receiver(); } // add event here if you need it } /* @notice Send funds in a receiver to another address @param ID - Receiver indexed ID @param tracker - ERC20 token tracker ( DAI / MKR / etc. ) @param amount - Amount of tokens to send @param receiver - Address we're sending tokens to @return true if transfer succeeded, false otherwise */ function sendFundsFromReceiverTo( uint256 ID, address tracker, uint256 amount, address receiver ) public returns (bool) { require(msg.sender == owner); return Receiver( receiversMap[ID] ).sendFundsTo( tracker, amount, receiver); } /* Batch Collection - Should support a few hundred transansfers @param tracker - ERC20 token tracker ( DAI / MKR / etc. ) @param receiver - Address we're sending tokens to @param contractAddresses - we send an array of addresses instead of ids, so we don't need to read them ( lower gas cost ) @param amounts - array of amounts */ function batchCollect( address tracker, address receiver, address[] contractAddresses, uint256[] amounts ) public { require(msg.sender == owner); for(uint256 i = 0; i < contractAddresses.length; i++) { // add exception handling Receiver( contractAddresses[i] ).sendFundsTo( tracker, amounts[i], receiver); } } }
接收方契約:
contract Receiver { address public owner; constructor() public { /* Deployer's address ( Factory in our case ) do not pass this as a constructor argument because etherscan will have issues displaying our validated source code */ owner = msg.sender; } /* @notice Transfer Ownership of this contract to another address @param newOwner - Address of the next Owner of the contract */ function transferOwner(address newOwner) public { require (msg.sender == owner); owner = newOwner; } /* @notice Send funds owned by this contract to another address @param tracker - ERC20 token tracker ( DAI / MKR / etc. ) @param amount - Amount of tokens to send @param receiver - Address we're sending these tokens to @return true if transfer succeeded, false otherwise */ function sendFundsTo( address tracker, uint256 amount, address receiver) public returns ( bool ) { // callable only by the owner, not using modifiers to improve readability require(msg.sender == owner); // Transfer tokens from this address to the receiver return ERC20(tracker).transfer(receiver, amount); } // depending on your system, you probably want to suicide this at some // point in the future, or reuse it for other clients }
答案基於 Micky Socaci 的解決方案here。整個解決方案,經過必要的修改,託管在My Github上,具有知識共享許可,因此可以放入任何程式碼庫。
如果這對您有幫助,將不勝感激:)。
我假設您不能僅根據發送地址來辨識令牌轉移者 - 否則這將是微不足道的(只需遵循 Transfer 事件)。
我個人不太明白為什麼元交易已經不是一件大事了。它們支持各種場景,尤其是在使用者輕鬆入職時。當然,他們有一些問題並且實施起來有點棘手,但是一旦正確實施,它應該可以正常工作。所以我的建議是進行元交易。
讓我們花點時間思考在正常令牌傳輸中,除了發件人地址之外,是否有可能通過其他方式辨識發件人。轉移代幣有兩種方式:直接轉移和批准檢索。
transfer(address recipient, uint256 amount)
.recipient
必須是您控制的一些錢包地址。所以要麼是特製的錢包,要麼是普通的錢包。這幾乎是您幼稚的解決方案。但另一個想法可能是考慮是否可以amount
以某種方式使用。如果您只有少數使用者和大量代幣(少量代幣不會產生太大影響),您可以通過代幣數量來辨識使用者。因此,例如,如果三個使用者需要發送 5000 個令牌,您可以指示第一個發送 5003 個令牌,第二個發送 5006,第三個發送 5009。這不是最好的解決方案,但實施起來容易且便宜,因此可能值得考慮。approve(address spender, uint256 amount)
加transferFrom(address sender, address recipient, uint256 amount)
。與第一個選項中的注意事項相同,因為使用者只啟動approve
事務,其餘的由您完成。