Contrat

Contrat
0x5dab71f734…ebb98a18bc

Solde WTG

200 WTG

4 332,26 FCFA (@ 21,66 FCFA/WTG)

Avoirs en tokens

1 token

≈ 0,00 FCFA voir ↓

Plus d'infos

Transactions envoyées1
Dernière activitéil y a 1 j
Première activitéil y a 1 j
Financé par

Code du contrat

✓ Vérifié

WintgAccount · Solidity v0.8.20+commit.a1b79de6 · optimiseur activé (200 runs) · licence MIT

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import {
    PackedUserOperation,
    IEntryPoint,
    IAccount,
    SIG_VALIDATION_SUCCESS,
    SIG_VALIDATION_FAILED,
    packValidationData
} from "./interfaces.sol";

contract WintgAccount is IAccount {
    using ECDSA for bytes32;

    IEntryPoint public immutable entryPoint;
    address public owner;

    address internal constant NATIVE = address(0);

    struct Session {
        bool exists;
        bool anyTarget;
        bool anySelector;
        uint48 validAfter;
        uint48 validUntil;
    }

    mapping(address => Session) public sessions;
    mapping(address => mapping(address => bool)) public sessionAllowedTarget;
    mapping(address => mapping(bytes4 => bool)) public sessionAllowedSelector;

    mapping(address => mapping(address => uint256)) public sessionDailyCap;
    mapping(address => mapping(address => uint256)) public sessionSpentToday;
    mapping(address => mapping(address => uint48)) public sessionDayIndex;

    address[] public guardians;
    mapping(address => bool) public isGuardian;
    uint256 public recoveryThreshold;
    address public recoveryProposed;
    uint256 public recoveryApprovals;
    uint256 public recoveryRound;
    mapping(address => uint256) public guardianApprovedRound;

    event OwnerChanged(address indexed newOwner);
    event SessionRegistered(address indexed key, uint48 validUntil);
    event SessionRevoked(address indexed key);
    event Executed(address indexed target, uint256 value, bytes data);
    event GuardiansSet(address[] guardians, uint256 threshold);
    event RecoveryProposed(address indexed guardian, address indexed newOwner);
    event RecoveryApproved(address indexed guardian, uint256 approvals);
    event Recovered(address indexed newOwner);

    error NotEntryPoint();
    error NotAuthorized();
    error LengthMismatch();
    error NotGuardian();
    error NoRecovery();

    constructor(address entryPoint_, address owner_) {
        entryPoint = IEntryPoint(entryPoint_);
        owner = owner_;
    }

    receive() external payable { }

    modifier onlyEntryPoint() {
        if (msg.sender != address(entryPoint)) revert NotEntryPoint();
        _;
    }

    modifier onlyOwnerControl() {
        if (msg.sender != owner && msg.sender != address(this) && msg.sender != address(entryPoint)) {
            revert NotAuthorized();
        }
        _;
    }

    function execute(address target, uint256 value, bytes calldata data) external {
        _requireExecutor();
        _call(target, value, data);
    }

    function executeBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata datas
    ) external {
        _requireExecutor();
        if (targets.length != values.length || targets.length != datas.length) {
            revert LengthMismatch();
        }
        for (uint256 i; i < targets.length; i++) {
            _call(targets[i], values[i], datas[i]);
        }
    }

    function _requireExecutor() internal view {
        if (msg.sender != address(entryPoint) && msg.sender != owner) revert NotAuthorized();
    }

    function _call(address target, uint256 value, bytes memory data) internal {
        (bool ok, bytes memory result) = target.call{ value: value }(data);
        if (!ok) {
            assembly {
                revert(add(result, 32), mload(result))
            }
        }
        emit Executed(target, value, data);
    }

    function validateUserOp(
        PackedUserOperation calldata userOp,
        bytes32 userOpHash,
        uint256 missingAccountFunds
    ) external onlyEntryPoint returns (uint256 validationData) {
        validationData = _validateSignature(userOp, userOpHash);
        _payPrefund(missingAccountFunds);
    }

    function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash)
        internal
        returns (uint256)
    {
        bytes32 hash = MessageHashUtils.toEthSignedMessageHash(userOpHash);
        (address signer, ECDSA.RecoverError err, ) = ECDSA.tryRecover(hash, userOp.signature);
        if (err != ECDSA.RecoverError.NoError) return SIG_VALIDATION_FAILED;

        if (signer == owner) return SIG_VALIDATION_SUCCESS;

        Session storage s = sessions[signer];
        if (!s.exists) return SIG_VALIDATION_FAILED;
        if (!_checkPolicy(signer, userOp.callData)) return SIG_VALIDATION_FAILED;
        return packValidationData(false, s.validUntil, s.validAfter);
    }

    function _checkPolicy(address key, bytes calldata callData) internal returns (bool) {
        if (callData.length < 4) return false;
        bytes4 sel = bytes4(callData[:4]);

        if (sel == this.execute.selector) {
            (address target, uint256 value, bytes memory data) =
                abi.decode(callData[4:], (address, uint256, bytes));
            return _checkSingle(key, target, value, data);
        } else if (sel == this.executeBatch.selector) {
            (address[] memory targets, uint256[] memory values, bytes[] memory datas) =
                abi.decode(callData[4:], (address[], uint256[], bytes[]));
            if (targets.length != values.length || targets.length != datas.length) return false;
            for (uint256 i; i < targets.length; i++) {
                if (!_checkSingle(key, targets[i], values[i], datas[i])) return false;
            }
            return true;
        }
        return false;
    }

    function _checkSingle(address key, address target, uint256 value, bytes memory data)
        internal
        returns (bool)
    {
        Session storage s = sessions[key];
        if (!s.anyTarget && !sessionAllowedTarget[key][target]) return false;
        if (!s.anySelector && !sessionAllowedSelector[key][_selectorOf(data)]) return false;

        if (value > 0 && !_spend(key, NATIVE, value)) return false;

        (uint256 tokenAmount, bool isSpend) = _tokenSpendAmount(data);
        if (isSpend && tokenAmount > 0 && !_spend(key, target, tokenAmount)) return false;

        return true;
    }

    function _spend(address key, address asset, uint256 amount) internal returns (bool) {
        uint256 cap = sessionDailyCap[key][asset];
        if (cap == 0) return true;
        uint48 today = uint48(block.timestamp / 1 days);
        uint256 spent = sessionDayIndex[key][asset] == today ? sessionSpentToday[key][asset] : 0;
        if (spent + amount > cap) return false;
        sessionSpentToday[key][asset] = spent + amount;
        sessionDayIndex[key][asset] = today;
        return true;
    }

    function _tokenSpendAmount(bytes memory d) internal pure returns (uint256 amount, bool isSpend) {
        if (d.length < 4) return (0, false);
        bytes4 sel = _selectorOf(d);
        if (sel == 0xa9059cbb && d.length >= 68) {
            return (_readWord(d, 36), true);
        } else if (sel == 0x23b872dd && d.length >= 100) {
            return (_readWord(d, 68), true);
        } else if (sel == 0x095ea7b3 && d.length >= 68) {
            return (_readWord(d, 36), true);
        }
        return (0, false);
    }

    function _readWord(bytes memory d, uint256 offset) internal pure returns (uint256 w) {
        assembly {
            w := mload(add(add(d, 32), offset))
        }
    }

    function _selectorOf(bytes memory d) internal pure returns (bytes4 sel) {
        if (d.length >= 4) {
            assembly {
                sel := mload(add(d, 32))
            }
        }
    }

    function _payPrefund(uint256 missingAccountFunds) internal {
        if (missingAccountFunds > 0) {
            (bool ok, ) = payable(msg.sender).call{ value: missingAccountFunds }("");
            ok;
        }
    }

    function registerSessionKey(
        address key,
        uint48 validAfter,
        uint48 validUntil,
        address[] calldata targets,
        bytes4[] calldata selectors,
        bool anyTarget,
        bool anySelector,
        address[] calldata capAssets,
        uint256[] calldata capDaily
    ) external onlyOwnerControl {
        if (capAssets.length != capDaily.length) revert LengthMismatch();
        sessions[key] = Session({
            exists: true,
            anyTarget: anyTarget,
            anySelector: anySelector,
            validAfter: validAfter,
            validUntil: validUntil
        });
        for (uint256 i; i < targets.length; i++) {
            sessionAllowedTarget[key][targets[i]] = true;
        }
        for (uint256 i; i < selectors.length; i++) {
            sessionAllowedSelector[key][selectors[i]] = true;
        }
        for (uint256 i; i < capAssets.length; i++) {
            sessionDailyCap[key][capAssets[i]] = capDaily[i];
            sessionSpentToday[key][capAssets[i]] = 0;
            sessionDayIndex[key][capAssets[i]] = 0;
        }
        emit SessionRegistered(key, validUntil);
    }

    function revokeSessionKey(address key) external onlyOwnerControl {
        delete sessions[key];
        emit SessionRevoked(key);
    }

    function transferOwnership(address newOwner) external onlyOwnerControl {
        require(newOwner != address(0), "WintgAccount: zero owner");
        owner = newOwner;
        emit OwnerChanged(newOwner);
    }

    modifier onlyGuardian() {
        if (!isGuardian[msg.sender]) revert NotGuardian();
        _;
    }

    function setGuardians(address[] calldata gs, uint256 threshold) external onlyOwnerControl {
        for (uint256 i; i < guardians.length; i++) {
            isGuardian[guardians[i]] = false;
        }
        delete guardians;
        require(threshold > 0 && threshold <= gs.length, "WintgAccount: bad threshold");
        for (uint256 i; i < gs.length; i++) {
            require(gs[i] != address(0) && !isGuardian[gs[i]], "WintgAccount: bad guardian");
            isGuardian[gs[i]] = true;
            guardians.push(gs[i]);
        }
        recoveryThreshold = threshold;
        recoveryProposed = address(0);
        recoveryApprovals = 0;
        recoveryRound++;
        emit GuardiansSet(gs, threshold);
    }

    function proposeRecovery(address newOwner) external onlyGuardian {
        require(newOwner != address(0), "WintgAccount: zero owner");
        recoveryRound++;
        recoveryProposed = newOwner;
        recoveryApprovals = 1;
        guardianApprovedRound[msg.sender] = recoveryRound;
        emit RecoveryProposed(msg.sender, newOwner);
        _maybeRecover();
    }

    function approveRecovery() external onlyGuardian {
        if (recoveryProposed == address(0)) revert NoRecovery();
        require(guardianApprovedRound[msg.sender] != recoveryRound, "WintgAccount: already approved");
        guardianApprovedRound[msg.sender] = recoveryRound;
        recoveryApprovals++;
        emit RecoveryApproved(msg.sender, recoveryApprovals);
        _maybeRecover();
    }

    function _maybeRecover() internal {
        if (recoveryApprovals >= recoveryThreshold) {
            owner = recoveryProposed;
            emit Recovered(owner);
            emit OwnerChanged(owner);
            recoveryProposed = address(0);
            recoveryApprovals = 0;
            recoveryRound++;
        }
    }

    function guardianCount() external view returns (uint256) {
        return guardians.length;
    }

    function addDeposit() external payable {
        entryPoint.depositTo{ value: msg.value }(address(this));
    }

    function getDeposit() external view returns (uint256) {
        return entryPoint.balanceOf(address(this));
    }

    function withdrawDepositTo(address payable to, uint256 amount) external onlyOwnerControl {
        entryPoint.withdrawTo(to, amount);
    }
}
[
    {
        "type": "constructor",
        "inputs": [
            {
                "name": "entryPoint_",
                "type": "address",
                "internalType": "address"
            },
            {
                "name": "owner_",
                "type": "address",
                "internalType": "address"
            }
        ],
        "stateMutability": "nonpayable"
    },
    {
        "type": "receive",
        "stateMutability": "payable"
    },
    {
        "type": "function",
        "name": "addDeposit",
        "inputs": [],
        "outputs": [],
        "stateMutability": "payable"
    },
    {
        "type": "function",
        "name": "approveRecovery",
        "inputs": [],
        "outputs": [],
        "stateMutability": "nonpayable"
    },
    {
        "type": "function",
        "name": "entryPoint",
        "inputs": [],
        "outputs": [
            {
                "name": "",
                "type": "address",
                "internalType": "contract IEntryPoint"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "execute",
        "inputs": [
            {
                "name": "target",
                "type": "address",
                "internalType": "address"
            },
            {
                "name": "value",
                "type": "uint256",
                "internalType": "uint256"
            },
            {
                "name": "data",
                "type": "bytes",
                "internalType": "bytes"
            }
        ],
        "outputs": [],
        "stateMutability": "nonpayable"
    },
    {
        "type": "function",
        "name": "executeBatch",
        "inputs": [
            {
                "name": "targets",
                "type": "address[]",
                "internalType": "address[]"
            },
            {
                "name": "values",
                "type": "uint256[]",
                "internalType": "uint256[]"
            },
            {
                "name": "datas",
                "type": "bytes[]",
                "internalType": "bytes[]"
            }
        ],
        "outputs": [],
        "stateMutability": "nonpayable"
    },
    {
        "type": "function",
        "name": "getDeposit",
        "inputs": [],
        "outputs": [
            {
                "name": "",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "guardianApprovedRound",
        "inputs": [
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            }
        ],
        "outputs": [
            {
                "name": "",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "guardianCount",
        "inputs": [],
        "outputs": [
            {
                "name": "",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "guardians",
        "inputs": [
            {
                "name": "",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "outputs": [
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "isGuardian",
        "inputs": [
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            }
        ],
        "outputs": [
            {
                "name": "",
                "type": "bool",
                "internalType": "bool"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "owner",
        "inputs": [],
        "outputs": [
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "proposeRecovery",
        "inputs": [
            {
                "name": "newOwner",
                "type": "address",
                "internalType": "address"
            }
        ],
        "outputs": [],
        "stateMutability": "nonpayable"
    },
    {
        "type": "function",
        "name": "recoveryApprovals",
        "inputs": [],
        "outputs": [
            {
                "name": "",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "recoveryProposed",
        "inputs": [],
        "outputs": [
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "recoveryRound",
        "inputs": [],
        "outputs": [
            {
                "name": "",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "recoveryThreshold",
        "inputs": [],
        "outputs": [
            {
                "name": "",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "registerSessionKey",
        "inputs": [
            {
                "name": "key",
                "type": "address",
                "internalType": "address"
            },
            {
                "name": "validAfter",
                "type": "uint48",
                "internalType": "uint48"
            },
            {
                "name": "validUntil",
                "type": "uint48",
                "internalType": "uint48"
            },
            {
                "name": "targets",
                "type": "address[]",
                "internalType": "address[]"
            },
            {
                "name": "selectors",
                "type": "bytes4[]",
                "internalType": "bytes4[]"
            },
            {
                "name": "anyTarget",
                "type": "bool",
                "internalType": "bool"
            },
            {
                "name": "anySelector",
                "type": "bool",
                "internalType": "bool"
            },
            {
                "name": "capAssets",
                "type": "address[]",
                "internalType": "address[]"
            },
            {
                "name": "capDaily",
                "type": "uint256[]",
                "internalType": "uint256[]"
            }
        ],
        "outputs": [],
        "stateMutability": "nonpayable"
    },
    {
        "type": "function",
        "name": "revokeSessionKey",
        "inputs": [
            {
                "name": "key",
                "type": "address",
                "internalType": "address"
            }
        ],
        "outputs": [],
        "stateMutability": "nonpayable"
    },
    {
        "type": "function",
        "name": "sessionAllowedSelector",
        "inputs": [
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            },
            {
                "name": "",
                "type": "bytes4",
                "internalType": "bytes4"
            }
        ],
        "outputs": [
            {
                "name": "",
                "type": "bool",
                "internalType": "bool"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "sessionAllowedTarget",
        "inputs": [
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            },
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            }
        ],
        "outputs": [
            {
                "name": "",
                "type": "bool",
                "internalType": "bool"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "sessionDailyCap",
        "inputs": [
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            },
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            }
        ],
        "outputs": [
            {
                "name": "",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "sessionDayIndex",
        "inputs": [
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            },
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            }
        ],
        "outputs": [
            {
                "name": "",
                "type": "uint48",
                "internalType": "uint48"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "sessionSpentToday",
        "inputs": [
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            },
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            }
        ],
        "outputs": [
            {
                "name": "",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "sessions",
        "inputs": [
            {
                "name": "",
                "type": "address",
                "internalType": "address"
            }
        ],
        "outputs": [
            {
                "name": "exists",
                "type": "bool",
                "internalType": "bool"
            },
            {
                "name": "anyTarget",
                "type": "bool",
                "internalType": "bool"
            },
            {
                "name": "anySelector",
                "type": "bool",
                "internalType": "bool"
            },
            {
                "name": "validAfter",
                "type": "uint48",
                "internalType": "uint48"
            },
            {
                "name": "validUntil",
                "type": "uint48",
                "internalType": "uint48"
            }
        ],
        "stateMutability": "view"
    },
    {
        "type": "function",
        "name": "setGuardians",
        "inputs": [
            {
                "name": "gs",
                "type": "address[]",
                "internalType": "address[]"
            },
            {
                "name": "threshold",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "outputs": [],
        "stateMutability": "nonpayable"
    },
    {
        "type": "function",
        "name": "transferOwnership",
        "inputs": [
            {
                "name": "newOwner",
                "type": "address",
                "internalType": "address"
            }
        ],
        "outputs": [],
        "stateMutability": "nonpayable"
    },
    {
        "type": "function",
        "name": "validateUserOp",
        "inputs": [
            {
                "name": "userOp",
                "type": "tuple",
                "internalType": "struct PackedUserOperation",
                "components": [
                    {
                        "name": "sender",
                        "type": "address",
                        "internalType": "address"
                    },
                    {
                        "name": "nonce",
                        "type": "uint256",
                        "internalType": "uint256"
                    },
                    {
                        "name": "initCode",
                        "type": "bytes",
                        "internalType": "bytes"
                    },
                    {
                        "name": "callData",
                        "type": "bytes",
                        "internalType": "bytes"
                    },
                    {
                        "name": "accountGasLimits",
                        "type": "bytes32",
                        "internalType": "bytes32"
                    },
                    {
                        "name": "preVerificationGas",
                        "type": "uint256",
                        "internalType": "uint256"
                    },
                    {
                        "name": "gasFees",
                        "type": "bytes32",
                        "internalType": "bytes32"
                    },
                    {
                        "name": "paymasterAndData",
                        "type": "bytes",
                        "internalType": "bytes"
                    },
                    {
                        "name": "signature",
                        "type": "bytes",
                        "internalType": "bytes"
                    }
                ]
            },
            {
                "name": "userOpHash",
                "type": "bytes32",
                "internalType": "bytes32"
            },
            {
                "name": "missingAccountFunds",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "outputs": [
            {
                "name": "validationData",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "stateMutability": "nonpayable"
    },
    {
        "type": "function",
        "name": "withdrawDepositTo",
        "inputs": [
            {
                "name": "to",
                "type": "address",
                "internalType": "address payable"
            },
            {
                "name": "amount",
                "type": "uint256",
                "internalType": "uint256"
            }
        ],
        "outputs": [],
        "stateMutability": "nonpayable"
    },
    {
        "type": "event",
        "name": "Executed",
        "inputs": [
            {
                "name": "target",
                "type": "address",
                "indexed": true,
                "internalType": "address"
            },
            {
                "name": "value",
                "type": "uint256",
                "indexed": false,
                "internalType": "uint256"
            },
            {
                "name": "data",
                "type": "bytes",
                "indexed": false,
                "internalType": "bytes"
            }
        ],
        "anonymous": false
    },
    {
        "type": "event",
        "name": "GuardiansSet",
        "inputs": [
            {
                "name": "guardians",
                "type": "address[]",
                "indexed": false,
                "internalType": "address[]"
            },
            {
                "name": "threshold",
                "type": "uint256",
                "indexed": false,
                "internalType": "uint256"
            }
        ],
        "anonymous": false
    },
    {
        "type": "event",
        "name": "OwnerChanged",
        "inputs": [
            {
                "name": "newOwner",
                "type": "address",
                "indexed": true,
                "internalType": "address"
            }
        ],
        "anonymous": false
    },
    {
        "type": "event",
        "name": "Recovered",
        "inputs": [
            {
                "name": "newOwner",
                "type": "address",
                "indexed": true,
                "internalType": "address"
            }
        ],
        "anonymous": false
    },
    {
        "type": "event",
        "name": "RecoveryApproved",
        "inputs": [
            {
                "name": "guardian",
                "type": "address",
                "indexed": true,
                "internalType": "address"
            },
            {
                "name": "approvals",
                "type": "uint256",
                "indexed": false,
                "internalType": "uint256"
            }
        ],
        "anonymous": false
    },
    {
        "type": "event",
        "name": "RecoveryProposed",
        "inputs": [
            {
                "name": "guardian",
                "type": "address",
                "indexed": true,
                "internalType": "address"
            },
            {
                "name": "newOwner",
                "type": "address",
                "indexed": true,
                "internalType": "address"
            }
        ],
        "anonymous": false
    },
    {
        "type": "event",
        "name": "SessionRegistered",
        "inputs": [
            {
                "name": "key",
                "type": "address",
                "indexed": true,
                "internalType": "address"
            },
            {
                "name": "validUntil",
                "type": "uint48",
                "indexed": false,
                "internalType": "uint48"
            }
        ],
        "anonymous": false
    },
    {
        "type": "event",
        "name": "SessionRevoked",
        "inputs": [
            {
                "name": "key",
                "type": "address",
                "indexed": true,
                "internalType": "address"
            }
        ],
        "anonymous": false
    },
    {
        "type": "error",
        "name": "LengthMismatch",
        "inputs": []
    },
    {
        "type": "error",
        "name": "NoRecovery",
        "inputs": []
    },
    {
        "type": "error",
        "name": "NotAuthorized",
        "inputs": []
    },
    {
        "type": "error",
        "name": "NotEntryPoint",
        "inputs": []
    },
    {
        "type": "error",
        "name": "NotGuardian",
        "inputs": []
    }
]
0x6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c80630b6cb271146101d95780630c68ba21146101d457806315f5198c146101cf57806319822f7c146101ca5780631c8123d6146101c5578063431a1b97146101c057806347e1da2a146101bb578063489ff39a146101b65780634a58db19146101b15780634b504f3b146101ac5780634d44560d146101a75780635202a39f146101a257806354387ad71461019d57806357aebcb61461019857806375aaf0df146101935780637ee760821461018e57806384f4fc6a14610189578063876b4e0d146101845780638da5cb5b1461017f578063aec9c19b1461017a578063b0d691fe14610175578063b61d27f614610170578063c399ec881461016b578063cd34312214610166578063dcd3cf9014610161578063f2fde38b1461015c578063f560c734146101575763fcae8d380361000e57610fdf565b610f98565b610ea9565b610e8c565b610e4f565b610da6565b610d41565b610cfd565b610cc2565b610c9b565b610a71565b6109c5565b610904565b61084c565b610799565b61076a565b610726565b61063b565b610613565b610594565b610559565b610451565b6103a8565b61038b565b6102ce565b610282565b61021a565b346101f6575f3660031901126101f6576020600b54604051908152f35b5f80fd5b6001600160a01b038116036101f657565b60043590610218826101fa565b565b346101f65760203660031901126101f657600435610237816101fa565b60018060a01b03165f526008602052602060ff60405f2054166040519015158152f35b60409060031901126101f657600435610272816101fa565b9060243561027f816101fa565b90565b346101f657602065ffffffffffff6102c461029c3661025a565b6001600160a01b039182165f9081526006865260408082209290931681526020919091522090565b5416604051908152f35b346101f6576003196060368201126101f657600435906001600160401b0382116101f6576101209082360301126101f6576044357f000000000000000000000000a8e7668576dc0b6490dba71fd53965b6ea4b913e6001600160a01b031633036103795761034561035d9260243590600401611313565b9080610361575b506040519081529081906020820190565b0390f35b5f80808093335af150610372611229565b505f61034c565b604051636b31ba1560e11b8152600490fd5b346101f6575f3660031901126101f6576020600954604051908152f35b346101f65760203660031901126101f6576004356103c5816101fa565b60018060a01b03165f52600160205260a060405f20546040519060ff81161515825260ff8160081c161515602083015260ff8160101c161515604083015265ffffffffffff90818160181c16606084015260481c166080820152f35b9181601f840112156101f6578235916001600160401b0383116101f6576020808501948460051b0101116101f657565b346101f65760603660031901126101f6576001600160401b036004358181116101f657610482903690600401610421565b91906024358281116101f65761049c903690600401610421565b926044359081116101f6576104b5903690600401610421565b9490926104c06111e0565b84821480159061054f575b61053a575f5b8281106104da57005b6104e5818484611194565b35906104f0826101fa565b6104fb818887611194565b3588821015610535576105309261052b9161052561051e8560051b8b018b6111ae565b3691611126565b91611258565b611181565b6104d1565b610f62565b6040516001621398b960e31b03198152600490fd5b50858214156104cb565b346101f65760203660031901126101f657600435610576816101fa565b60018060a01b03165f52600d602052602060405f2054604051908152f35b5f80600319360112610610577f000000000000000000000000a8e7668576dc0b6490dba71fd53965b6ea4b913e6001600160a01b031681813b156106105760405163b760faf960e01b8152306004820152918290602490829034905af1801561060b576105ff575080f35b610608906110b3565b80f35b611453565b80fd5b346101f6575f3660031901126101f657600a546040516001600160a01b039091168152602090f35b346101f6575f604036600319011261061057600435610659816101fa565b81546001600160a01b039081163314158061071c575b806106f0575b6106de578083917f000000000000000000000000a8e7668576dc0b6490dba71fd53965b6ea4b913e1692833b156106da5760449083604051958694859363040b850f60e31b855216600484015260243560248401525af1801561060b576105ff575080f35b8280fd5b60405163ea8e4eb560e01b8152600490fd5b50807f000000000000000000000000a8e7668576dc0b6490dba71fd53965b6ea4b913e16331415610675565b503033141561066f565b346101f65760206107616107393661025a565b6001600160a01b039182165f9081526005855260408082209290931681526020919091522090565b54604051908152f35b346101f6575f3660031901126101f6576020600754604051908152f35b6001600160e01b03198116036101f657565b346101f65760403660031901126101f657602060ff6107f86004356107bd816101fa565b602435906107ca82610787565b6001600160a01b03165f9081526003855260408082206001600160e01b031990931682526020929092522090565b54166040519015158152f35b6024359065ffffffffffff821682036101f657565b6044359065ffffffffffff821682036101f657565b60a4359081151582036101f657565b60c4359081151582036101f657565b346101f6576101203660031901126101f65761086661020b565b61086e610804565b610876610819565b6001600160401b0392906064358481116101f657610898903690600401610421565b6084929192358681116101f6576108b3903690600401610421565b6108bb61082e565b916108c461083d565b9360e4358a81116101f6576108dd903690600401610421565b979096610104359b8c116101f6576108fc6100189c3690600401610421565b9b909a611c81565b346101f65760203660031901126101f657600435610921816101fa565b5f90338252600860205260ff604083205416156109b3576001600160a01b031661094c811515611f7c565b610957600c54611181565b80600c55816bffffffffffffffffffffffff60a01b600a541617600a556001600b55338352600d6020526040832055337fe189fc861f89a82adac6d12e9bb4465f134bae5af630f6045087e93257dff6248380a3610608612190565b6040516377b6878160e11b8152600490fd5b346101f65760203660031901126101f6576004356109e2816101fa565b5f805490916001600160a01b0391821633141580610a67575b80610a3b575b6106de571680825260016020528160408120557f2991ab7bfda4556c9e662762b3dfa89a1df391084c4278286d466c1c187e55238280a280f35b50817f000000000000000000000000a8e7668576dc0b6490dba71fd53965b6ea4b913e16331415610a01565b50303314156109fb565b346101f65760403660031901126101f6576004356001600160401b0381116101f657610aa1903690600401610421565b5f54602435929190336001600160a01b0391821614159081610c90575b81610c63575b506106de575f5b600754811015610b28578061052b610b19610b00610aeb610b2395610f76565b905460039190911b1c6001600160a01b031690565b6001600160a01b03165f90815260086020526040902090565b805460ff19169055565b610acb565b5090610b32611fc8565b82151580610c59575b610b4490612007565b5f5b828110610bb95750610bb483610b7c7f61c3ef76fc3a3e366dde2fc8881a1e9504f76f52692a251bd4b11d79d2fa69c495600955565b600a80546001600160a01b0319169055610b955f600b55565b610ba8610ba3600c54611181565b600c55565b604051938493846120f4565b0390a1005b80610bdf610bd3610bce610c27948787611194565b6111a4565b6001600160a01b031690565b151580610c2c575b610bf090612053565b610c11610c04610b00610bce848888611194565b805460ff19166001179055565b61052b610c22610bce838787611194565b61209f565b610b46565b50610bf0610c52610c4e610c47610b00610bce868a8a611194565b5460ff1690565b1590565b9050610be7565b5081831115610b3b565b90507f000000000000000000000000a8e7668576dc0b6490dba71fd53965b6ea4b913e163314155f610ac4565b333014159150610abe565b346101f6575f3660031901126101f6575f546040516001600160a01b039091168152602090f35b346101f6576020610761610cd53661025a565b6001600160a01b039182165f9081526004855260408082209290931681526020919091522090565b346101f6575f3660031901126101f6576040517f000000000000000000000000a8e7668576dc0b6490dba71fd53965b6ea4b913e6001600160a01b03168152602090f35b346101f65760603660031901126101f657600435610d5e816101fa565b604435906001600160401b03908183116101f657366023840112156101f65782600401359182116101f65736602483850101116101f65760246100189301906024359061115c565b346101f6575f80600319360112610610576040516370a0823160e01b81523060048201526020816024817f000000000000000000000000a8e7668576dc0b6490dba71fd53965b6ea4b913e6001600160a01b03165afa90811561060b578291610e15575b604051828152602090f35b90506020813d8211610e47575b81610e2f602093836110cb565b81010312610e435761035d9150515f610e0a565b5080fd5b3d9150610e22565b346101f657602060ff6107f8610e643661025a565b6001600160a01b039182165f9081526002865260408082209290931681526020919091522090565b346101f6575f3660031901126101f6576020600c54604051908152f35b346101f65760203660031901126101f657600435610ec6816101fa565b5f805490916001600160a01b039033828416141580610f58575b80610f2c575b6106de57168091610ef8821515611f7c565b6001600160a01b0319161782557fa2ea9883a321a3e97b8266c2b078bfeec6d50c711ed71f874a90d500ae2eaf368280a280f35b50817f000000000000000000000000a8e7668576dc0b6490dba71fd53965b6ea4b913e16331415610ee6565b5030331415610ee0565b634e487b7160e01b5f52603260045260245ffd5b6007548110156105355760075f525f8051602061221e83398151915201905f90565b346101f65760203660031901126101f6576004356007548110156101f65760075f525f8051602061221e83398151915201546040516001600160a01b039091168152602090f35b346101f6575f8060031936011261061057338152600860205260ff604082205416156109b357600a546001600160a01b03161561108d57338152600d6020526040812054611032600c5480921415612144565b335f908152600d602052604090205561105461104f600b54611181565b600b55565b600b5460405190815233907f56f39088d9ede6ed9c5cc202888ed11dcbd4e5e85d63d648f1b73528efccb93a90602090a2610608612190565b60405163c993b99360e01b8152600490fd5b634e487b7160e01b5f52604160045260245ffd5b6001600160401b0381116110c657604052565b61109f565b90601f801991011681019081106001600160401b038211176110c657604052565b6040519060a082018281106001600160401b038211176110c657604052565b6001600160401b0381116110c657601f01601f191660200190565b9291926111328261110b565b9161114060405193846110cb565b8294818452818301116101f6578281602093845f960137010152565b91610525906102189461051e6111e0565b634e487b7160e01b5f52601160045260245ffd5b5f19811461118f5760010190565b61116d565b91908110156105355760051b0190565b3561027f816101fa565b903590601e19813603018212156101f657018035906001600160401b0382116101f6576020019181360383136101f657565b60018060a01b03807f000000000000000000000000a8e7668576dc0b6490dba71fd53965b6ea4b913e16331415908161121b575b506106de57565b90505f54163314155f611214565b3d15611253573d9061123a8261110b565b9161124860405193846110cb565b82523d5f602084013e565b606090565b82515f8060209283870186865af161126e611229565b90156112ef57506040519283526040818401528351938460408501525f5b8581106112db57505050906060817fcaf938de11c367272220bfd1d2baa99ca46665e7bc4d85f00adb51b90fe1fa9f935f83878401015260018060a01b031694601f80199101168101030190a2565b81810183015185820160600152820161128c565b80519101fd5b600411156112ff57565b634e487b7160e01b5f52602160045260245ffd5b9061134861135f917f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f52601c52603c5f2090565b61135961051e6101008501856111ae565b90611419565b50611369816112f5565b611412575f54611381906001600160a01b0316610bd3565b6001600160a01b0382161461140c576001600160a01b0381165f908152600160205260409020916113b6610c4e845460ff1690565b611404576113d5916113cf826060610c4e9401906111ae565b9161174b565b6113fe5754605881901b65ffffffffffff60a01b1660b89190911b6001600160d01b0319161790565b50600190565b505050600190565b50505f90565b5050600190565b8151919060418303611449576114429250602082015190606060408401519301515f1a9061145e565b9192909190565b50505f9160029190565b6040513d5f823e3d90fd5b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a084116114d557926020929160ff6080956040519485521684840152604083015260608201525f92839182805260015afa1561060b5780516001600160a01b038116156114cc57918190565b50809160019190565b5050505f9160039190565b906004116101f65790600490565b90929192836004116101f65783116101f657600401916003190190565b6001600160e01b0319903581811693926004811061152857505050565b60040360031b82901b16169150565b6001600160401b0381116110c65760051b60200190565b81601f820112156101f65780359161156583611537565b9261157360405194856110cb565b808452602092838086019260051b8201019283116101f6578301905b82821061159d575050505090565b8135815290830190830161158f565b9080601f830112156101f65781602061027f93359101611126565b9080601f830112156101f6578135906115df82611537565b926115ed60405194856110cb565b828452602092838086019160051b830101928084116101f657848301915b84831061161b5750505050505090565b82356001600160401b0381116101f657869161163c848480948901016115ac565b81520192019161160b565b90916060828403126101f6576001600160401b039180358381116101f65781019380601f860112156101f657843561167e81611537565b9061168c60405192836110cb565b808252602096878084019260051b820101918483116101f65788809201905b8382106116e45750505050948201358481116101f657816116cd91840161154e565b9360408301359081116101f65761027f92016115c7565b82809183356116f2816101fa565b8152019101906116ab565b80518210156105355760209160051b010190565b916060838303126101f6578235611727816101fa565b9260208101359260408201356001600160401b0381116101f65761027f92016115ac565b9190600482106118725761177261176283836114e0565b6001600160e01b0319929161150b565b16635b0e93fb60e11b81036117ae57506117948261027f949361179c936114ee565b810190611711565b9290916001600160a01b031690611879565b6323f0ed1560e11b146117c2575050505f90565b816117d8926117d0926114ee565b810190611647565b929180518251811490811591611866575b5061185e575f92835b825181101561185357611838610c4e61181b61180e84876116fd565b516001600160a01b031690565b61182584886116fd565b51611830858b6116fd565b519186611879565b61184a5761184590611181565b6117f2565b50505050905090565b505050505050600190565b505050505f90565b9050845114155f6117e9565b5050505f90565b6001600160a01b0381165f90815260016020526040902090939192905460ff8160081c161580611974575b61196b5760101c60ff161580611924575b61185e57801515908161190f575b50611872576118d190611bba565b9182611905575b826118ef575b505090506118eb57600190565b5f90565b610c4e92506118fd93611af1565b805f806118de565b81151592506118d8565b61191e9150610c4e90856119c0565b5f6118c3565b50611966610c4e610c476119488760018060a01b03165f52600360205260405f2090565b61195186611c69565b63ffffffff60e01b165f5260205260405f2090565b6118b5565b50505050505f90565b506119ae610c4e610c47866119998960018060a01b03165f52600260205260405f2090565b9060018060a01b03165f5260205260405f2090565b6118a4565b9190820180921161118f57565b6001600160a01b0381165f90815260046020526040902090915f9182805260205260408220548015611ae85765ffffffffffff9283620151804204168094611a188760018060a01b03165f52600660205260405f2090565b838052602052604083205465ffffffffffff161603611ae1576001600160a01b0385165f908152600560205260409020611a5a905b5f805260205260405f2090565b54915b611a6784846119b3565b11611ad95750611ad493611a81611abb93611a4d936119b3565b6001600160a01b0382165f908152600560205260409020611aa190611a4d565b556001600160a01b03165f90815260066020526040902090565b9065ffffffffffff1665ffffffffffff19825416179055565b600190565b935050505090565b8091611a5d565b50505050600190565b6001600160a01b0381165f908152600460205260409020611b13908390611999565b54918215611ae85765ffffffffffff9283620151804204168094611b4b846119998760018060a01b03165f52600660205260405f2090565b5416145f905f14611bb457506001600160a01b0383165f908152600560205260409020611b79908390611999565b54945b850180951161118f57841161185e5761199982611ad495611aa184611999611abb9760018060a01b03165f52600560205260405f2090565b94611b7c565b805160048110611c61576001600160e01b0319611bd683611c69565b1663a9059cbb60e01b811480611c56575b15611bf85750506044015190600190565b6323b872dd60e01b811480611c4b575b15611c195750506064015190600190565b63095ea7b360e01b149081611c3f575b50611c3557505f905f90565b6044015190600190565b6044915010155f611c29565b506064821015611c08565b506044821015611be7565b50505f905f90565b905f91600481511015611c795750565b602001519150565b99969a98979593919b94929060018060a01b039b5f978d89541633141580611ecf575b80611ea3575b6106de57878a0361053a578e611cf5611d2094611ce6611d0494611cdd611ccf6110ec565b600181529715156020890152565b15156040870152565b65ffffffffffff166060850152565b65ffffffffffff166080830152565b6001600160a01b038c165f908152600160205260409020611ed9565b89865b838110611e6b5750505050835b828110611e2f57505050815b838110611d8457505060405165ffffffffffff9790971687525050509116917f012bd62476491e60f5e45ed69c1717c5a41d48b470ba8413d7c516458fd8e3c99150602090a2565b80611d93611e2a928489611194565b35611dd3611db18a60018060a01b03165f52600460205260405f2090565b611dbf610bce858a8c611194565b60018060a01b03165f5260205260405f2090565b556001600160a01b0388165f9081526005602052604090208490611df690611db1565b556001600160a01b0388165f90815260066020526040902061052b90611e1b90611db1565b805465ffffffffffff19169055565b611d3c565b611e669061052b610c04611e538c60018060a01b03165f52600360205260405f2090565b611951611e61858989611194565b611f72565b611d30565b61052b610c04611e8e611e9c9460018060a01b03165f52600260205260405f2090565b611dbf610bce858989611194565b8a90611d23565b508d7f000000000000000000000000a8e7668576dc0b6490dba71fd53965b6ea4b913e16331415611caa565b5030331415611ca4565b8151815460208401516040850151606086015168ffffffffffff00000060189190911b1668ffffffffffffffffff1990931693151560ff169390931761ff0091151560081b919091161762ff000092151560101b929092169190911717815561021891611f4f906080015165ffffffffffff1690565b65ffffffffffff60481b82549160481b169065ffffffffffff60481b1916179055565b3561027f81610787565b15611f8357565b60405162461bcd60e51b815260206004820152601860248201527f57696e74674163636f756e743a207a65726f206f776e657200000000000000006044820152606490fd5b6007545f8060075581611fd9575050565b600781525f8051602061221e833981519152918201915b828110611ffc57505050565b818155600101611ff0565b1561200e57565b60405162461bcd60e51b815260206004820152601b60248201527f57696e74674163636f756e743a20626164207468726573686f6c6400000000006044820152606490fd5b1561205a57565b60405162461bcd60e51b815260206004820152601a60248201527f57696e74674163636f756e743a2062616420677561726469616e0000000000006044820152606490fd5b600754680100000000000000008110156110c65760018101806007558110156105355760075f525f8051602061221e8339815191520180546001600160a01b0319166001600160a01b03909216919091179055565b6040808252810183905293929160608501905f5b81811061211a57505060209150930152565b9091600190843561212a816101fa565b60a083901b83900316815260209485019401929101612108565b1561214b57565b60405162461bcd60e51b815260206004820152601e60248201527f57696e74674163636f756e743a20616c726561647920617070726f76656400006044820152606490fd5b600b54600954111561219e57565b600a545f80546001600160a01b0383166001600160a01b03199182168117835591929091807f5e06a4da1c258ba9bc6142ca9e5b6dfa64e57f7fc4e91a150ba0b3fd301587a08580a27fa2ea9883a321a3e97b8266c2b078bfeec6d50c711ed71f874a90d500ae2eaf368480a216600a55600b55610ba3600c5461118156fea66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688a264697066735822122047f03e01c3c37d8f3f068e471e5f1df2ce699b361d77417b76d8630faa9bc27464736f6c63430008140033

Avoirs

WCFA

190769.6474 WCFA
HashMéthodeBlocÂgeDeÀMontantFrais
0xf6a0425e13… Exécution (AA) 35 052 il y a 1 j 0x39b5f0…2bbf11 ENTR. 0x5dab71…8a18bc 0.00005661 WTG
0x2d1ecfad35… Transfert 35 047 il y a 1 j 0x835164…ee75cc ENTR. 0x5dab71…8a18bc 200 WTG
≈ 4 332,26 FCFA
0.00002106 WTG
WINTG CFA · il y a 9 min
0.329 WCFA
WINTG CFA · il y a 9 min
5 WCFA
WINTG CFA · il y a 10 min
12 WCFA
WINTG CFA · il y a 27 min
0.329 WCFA
WINTG CFA · il y a 27 min
40 WCFA
WINTG CFA · il y a 33 min
0.329 WCFA
WINTG CFA · il y a 33 min
10 WCFA
WINTG CFA · il y a 37 min
0.329 WCFA
WINTG CFA · il y a 37 min
28 WCFA
WINTG CFA · il y a 38 min
9 WCFA
WINTG CFA · il y a 42 min
30 WCFA
WINTG CFA · il y a 58 min
0.329 WCFA
WINTG CFA · il y a 58 min
46 WCFA
WINTG CFA · il y a 1 h
4 WCFA
WINTG CFA · il y a 1 h
22 WCFA
WINTG CFA · il y a 1 h
34 WCFA
WINTG CFA · il y a 1 h
37 WCFA
WINTG CFA · il y a 1 h
42 WCFA
WINTG CFA · il y a 1 h
50 WCFA
WINTG CFA · il y a 1 h
21 WCFA
WINTG CFA · il y a 1 h
48 WCFA
WINTG CFA · il y a 1 h
26 WCFA
WINTG CFA · il y a 1 h
28 WCFA
WINTG CFA · il y a 1 h
0.329 WCFA
WINTG CFA · il y a 1 h
33 WCFA
Tx parenteTypeDeÀValeur
0xe6fb254e…dd2575 création 0xcbca50…e4fcca 0x5dab71…8a18bc 0 WTG
≈ 0,00 FCFA