Permit Token 是 ERC20 代幣的擴充,在代幣合約中新增 permit 函式,能夠透過提交簽章來實現代幣的授權,用戶便可以透過簽章請別人代送交易。
規格說 ERC20 代幣需要新增以下三個函式:
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external
function nonces(address owner) external view returns (uint)
function DOMAIN_SEPARATOR() external view returns (bytes32)
直接看 openzeppelin ERC20Permit.sol 對 permit function 的實作:
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
if (block.timestamp > deadline) {
revert ERC2612ExpiredSignature(deadline);
}
bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));
bytes32 hash = _hashTypedDataV4(structHash);
address signer = ECDSA.recover(hash, v, r, s);
if (signer != owner) {
revert ERC2612InvalidSigner(signer, owner);
}
_approve(owner, spender, value);
}
如果一個 ERC20 代幣有支援 permit 功能,那可以寫一份簡單的合約,透過簽章來轉代幣:
contract GaslessTransfer {
function send(
address token,
address sender,
address receiver,
uint256 amount,
uint256 fee,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
IERC20Permit(token).permit(sender, address(this), amount + fee, deadline, v, r, s);
IERC20(token).transferFrom(sender, receiver, amount);
IERC20(token).transferFrom(sender, msg.sender, fee);
}
}
透過簽章轉代幣的好處是,只要持有簽章就能提交交易到區塊鏈,不一定要是傳送代幣的本人,因此可以做到「代付手續費」的功能。
免手續費 (gasless) 不是代表鏈上操作真的不用手續費,而是背後可能有其他人或公司願意幫你出手續費。
實作通常會直接引套件,以下筆記來自 ERC-2612 的 Security Considerations:
ecrecover
接受錯誤訊息時,會得到零地址,確保 owner != address(0)
。Permit2 是 Uniswap 實作的一個合約的名字。
對於已部署的代幣,無法新增 permit 功能,用戶要跟合約互動時,還是得送兩筆交易 (approve 和 transferFrom)。
Uniswap 的 Permit2 合約,提供一基礎建設,讓用戶一次性 approve 給 Permit2 合約,之後就能以送簽章來授權的方式,跟整合 Permit2 合約的合約進行互動,解決無 Permit 功能的代幣也能透過簽章做授權,前提是用戶還是得先 approve 給 Permit2 合約。詳情見:Uniswap Permit2 實作與設計。
Permit 功能僅針對 ERC20 approve 函式進行簽章化的功能,目的是讓未來的 ERC20 代幣有此功能。若你要讓你合約內所有函式都能透過簽章來交易,可以使用 openzeppelin 的 Meta Transactions 套件,來自於 ERC2771。
isValidSignature
,建議實作 SCA 時支援此函式,用來驗證代表此 SCA 的「訊息」與「簽章」是否有效。PS: 同時參賽中的作者剛好有一篇類似主題:Web3:從新手村開始 - Lv13 新手訓練營 : 惡意簽名