Write your first permission
The contract
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {IPermission, Context} from "@sail/interfaces/IPermission.sol";
/// Authorizes ERC-20 transfer(to, amount) calls, but only to `allowedRecipient`,
/// only on `allowedToken`, and only up to `maxAmount`.
contract TransferToRecipientPermission is IPermission {
bytes4 private constant TRANSFER_SELECTOR = 0xa9059cbb; // transfer(address,uint256)
address public immutable allowedToken;
address public immutable allowedRecipient;
uint256 public immutable maxAmount;
constructor(address token, address recipient, uint256 max) {
allowedToken = token;
allowedRecipient = recipient;
maxAmount = max;
}
function evaluate(bytes calldata txData, Context calldata ctx)
external view returns (bool)
{
// 1. Token calls carry no ETH.
if (ctx.value != 0) return false;
// 2. Only the allowlisted token.
if (ctx.target != allowedToken) return false;
// 3. Only the transfer selector.
if (ctx.selector != TRANSFER_SELECTOR) return false;
// 4. Length check before decoding: 4 + 32 + 32 = 68 bytes.
if (txData.length < 68) return false;
// 5. Decode and check the arguments.
(address to, uint256 amount) = abi.decode(txData[4:], (address, uint256));
if (to != allowedRecipient) return false;
if (amount > maxAmount) return false;
return true;
}
function discriminator() external pure returns (bytes32) {
return keccak256("TransferToRecipientPermission");
}
}Why each line is there
Gas
Test it off-chain first
Next
Last updated

