编译器
0.6.12+commit.27d51765
文件 1 的 20:Account.sol
pragma solidity ^0.6.12;
import "../access/Controlled.sol";
import "./AccountBase.sol";
contract Account is Controlled, AccountBase {
address public implementation;
constructor(
address registry_,
address implementation_
)
public
Controlled()
{
registry = registry_;
implementation = implementation_;
}
receive()
external
payable
{
}
fallback()
external
{
if (msg.data.length != 0) {
address implementation_ = implementation;
assembly {
let calldedatasize := calldatasize()
calldatacopy(0, 0, calldedatasize)
let result := delegatecall(gas(), implementation_, 0, calldedatasize, 0, 0)
let returneddatasize := returndatasize()
returndatacopy(0, 0, returneddatasize)
switch result
case 0 { revert(0, returneddatasize) }
default { return(0, returneddatasize) }
}
}
}
function setImplementation(
address implementation_
)
external
onlyController
{
implementation = implementation_;
}
function executeTransaction(
address to,
uint256 value,
bytes calldata data
)
external
onlyController
returns (bytes memory)
{
bytes memory result;
bool succeeded;
(succeeded, result) = payable(to).call{value: value}(data);
require(
succeeded,
"Account: transaction reverted"
);
return result;
}
}
文件 2 的 20:AccountBase.sol
pragma solidity ^0.6.12;
contract AccountBase {
address public registry;
}
文件 3 的 20:AccountController.sol
pragma solidity ^0.6.12;
import "./Account.sol";
contract AccountController {
address public accountRegistry;
address public accountImplementation;
event AccountRegistryUpdated(
address accountRegistry
);
event AccountImplementationUpdated(
address accountImplementation
);
event AccountDeployed(
address account,
address accountImplementation
);
event AccountUpgraded(
address account,
address accountImplementation
);
event AccountTransactionExecuted(
address account,
address to,
uint256 value,
bytes data,
bytes response
);
constructor() internal {}
function _initializeAccountController(
address accountRegistry_,
address accountImplementation_
)
internal
{
_setAccountRegistry(accountRegistry_, false);
_setAccountImplementation(accountImplementation_, false);
}
function _setAccountRegistry(
address accountRegistry_,
bool emitEvent
)
internal
{
require(
accountRegistry_ != address(0),
"AccountController: cannot set account registry to 0x0"
);
accountRegistry = accountRegistry_;
if (emitEvent) {
emit AccountRegistryUpdated(accountRegistry);
}
}
function _setAccountImplementation(
address accountImplementation_,
bool emitEvent
)
internal
{
require(
accountImplementation_ != address(0),
"AccountController: cannot set account Implementation to 0x0"
);
accountImplementation = accountImplementation_;
if (emitEvent) {
emit AccountImplementationUpdated(accountImplementation);
}
}
function _deployAccount(
bytes32 salt,
bool emitEvent
)
internal
returns (address)
{
address account = address(new Account{salt: salt}(
accountRegistry,
accountImplementation
));
if (emitEvent) {
emit AccountDeployed(
account,
accountImplementation
);
}
return account;
}
function _upgradeAccount(
address account,
bool emitEvent
)
internal
{
require(
Account(payable(account)).implementation() != accountImplementation,
"AccountController: account already upgraded"
);
Account(payable(account)).setImplementation(accountImplementation);
if (emitEvent) {
emit AccountUpgraded(
account,
accountImplementation
);
}
}
function _executeAccountTransaction(
address account,
address to,
uint256 value,
bytes memory data,
bool emitEvent
)
internal
returns (bytes memory)
{
require(
to != address(0),
"AccountController: cannot send to 0x0"
);
require(
to != address(this),
"AccountController: cannot send to controller"
);
require(
to != account,
"AccountController: cannot send to self"
);
bytes memory response = Account(payable(account)).executeTransaction(
to,
value,
data
);
if (emitEvent) {
emit AccountTransactionExecuted(
account,
to,
value,
data,
response
);
}
return response;
}
function _computeAccountAddress(
bytes32 salt
)
internal
view
returns (address)
{
bytes memory creationCode = abi.encodePacked(
type(Account).creationCode,
bytes12(0),
accountRegistry,
bytes12(0),
accountImplementation
);
bytes32 data = keccak256(
abi.encodePacked(
bytes1(0xff),
address(this),
salt,
keccak256(creationCode)
)
);
return address(uint160(uint256(data)));
}
}
文件 4 的 20:AccountRegistry.sol
pragma solidity ^0.6.12;
import "./Account.sol";
abstract contract AccountRegistry {
function isValidAccountSignature(
address account,
bytes32 messageHash,
bytes calldata signature
)
virtual
external
view
returns (bool);
function isValidAccountSignature(
address account,
bytes calldata message,
bytes calldata signature
)
virtual
external
view
returns (bool);
}
文件 5 的 20:BlockLib.sol
pragma solidity ^0.6.12;
library BlockLib {
struct BlockRelated {
bool added;
uint256 removedAtBlockNumber;
}
function verifyAtCurrentBlock(
BlockRelated memory self
)
internal
view
returns (bool)
{
return verifyAtBlock(self, block.number);
}
function verifyAtAnyBlock(
BlockRelated memory self
)
internal
pure
returns (bool)
{
return verifyAtBlock(self, 0);
}
function verifyAtBlock(
BlockRelated memory self,
uint256 blockNumber
)
internal
pure
returns (bool)
{
bool result = false;
if (self.added) {
if (self.removedAtBlockNumber == 0) {
result = true;
} else if (blockNumber == 0) {
result = true;
} else {
result = self.removedAtBlockNumber > blockNumber;
}
}
return result;
}
}
文件 6 的 20:BytesLib.sol
pragma solidity ^0.6.12;
library BytesLib {
function toAddress(
bytes memory data
)
internal
pure
returns (address)
{
address result;
require(
data.length == 20,
"BytesLib: invalid data length"
);
assembly {
result := div(mload(add(data, 0x20)), 0x1000000000000000000000000)
}
return result;
}
}
文件 7 的 20:Controlled.sol
pragma solidity ^0.6.12;
contract Controlled {
address public controller;
modifier onlyController() {
require(
msg.sender == controller,
"Controlled: msg.sender is not the controller"
);
_;
}
constructor()
internal
{
controller = msg.sender;
}
}
文件 8 的 20:ECDSAExtendedLib.sol
pragma solidity ^0.6.12;
import "./StringsLib.sol";
library ECDSAExtendedLib {
using StringsLib for uint;
function toEthereumSignedMessageHash(
bytes memory message
)
internal
pure
returns (bytes32)
{
return keccak256(abi.encodePacked(
"\x19Ethereum Signed Message:\n",
message.length.toString(),
abi.encodePacked(message)
));
}
}
文件 9 的 20:ECDSALib.sol
pragma solidity ^0.6.12;
library ECDSALib {
function recoverAddress(
bytes32 messageHash,
bytes memory signature
)
internal
pure
returns (address)
{
address result = address(0);
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
if (v < 27) {
v += 27;
}
if (v == 27 || v == 28) {
result = ecrecover(messageHash, v, r, s);
}
}
return result;
}
function toEthereumSignedMessageHash(
bytes32 messageHash
)
internal
pure
returns (bytes32)
{
return keccak256(abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
messageHash
));
}
}
文件 10 的 20:ERC20Token.sol
pragma solidity ^0.6.12;
import "../libs/SafeMathLib.sol";
contract ERC20Token {
using SafeMathLib for uint256;
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
mapping(address => uint256) internal balances;
mapping(address => mapping(address => uint256)) internal allowances;
event Transfer(
address indexed from,
address indexed to,
uint256 value
);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
constructor() internal {}
function transfer(
address to,
uint256 value
)
external
returns (bool)
{
_transfer(_getSender(), to, value);
return true;
}
function transferFrom(
address from,
address to,
uint256 value
)
virtual
external
returns (bool)
{
address sender = _getSender();
_transfer(from, to, value);
_approve(from, sender, allowances[from][sender].sub(value));
return true;
}
function approve(
address spender,
uint256 value
)
virtual
external
returns (bool)
{
_approve(_getSender(), spender, value);
return true;
}
function balanceOf(
address owner
)
virtual
external
view
returns (uint256)
{
return balances[owner];
}
function allowance(
address owner,
address spender
)
virtual
external
view
returns (uint256)
{
return allowances[owner][spender];
}
function _transfer(
address from,
address to,
uint256 value
)
virtual
internal
{
require(
from != address(0),
"ERC20Token: cannot transfer from 0x0 address"
);
require(
to != address(0),
"ERC20Token: cannot transfer to 0x0 address"
);
balances[from] = balances[from].sub(value);
balances[to] = balances[to].add(value);
emit Transfer(from, to, value);
}
function _approve(
address owner,
address spender,
uint256 value
)
virtual
internal
{
require(
owner != address(0),
"ERC20Token: cannot approve from 0x0 address"
);
require(
spender != address(0),
"ERC20Token: cannot approve to 0x0 address"
);
allowances[owner][spender] = value;
emit Approval(owner, spender, value);
}
function _mint(
address owner,
uint256 value
)
virtual
internal
{
require(
owner != address(0),
"ERC20Token: cannot mint to 0x0 address"
);
require(
value > 0,
"ERC20Token: cannot mint 0 value"
);
balances[owner] = balances[owner].add(value);
totalSupply = totalSupply.add(value);
emit Transfer(address(0), owner, value);
}
function _burn(
address owner,
uint256 value
)
virtual
internal
{
require(
owner != address(0),
"ERC20Token: cannot burn from 0x0 address"
);
balances[owner] = balances[owner].sub(
value,
"ERC20Token: burn value exceeds balance"
);
totalSupply = totalSupply.sub(value);
emit Transfer(owner, address(0), value);
}
function _getSender()
virtual
internal
view
returns (address)
{
return msg.sender;
}
}
文件 11 的 20:ExternalAccountRegistry.sol
pragma solidity ^0.6.12;
import "../common/libs/BlockLib.sol";
contract ExternalAccountRegistry {
using BlockLib for BlockLib.BlockRelated;
struct Account {
mapping(address => BlockLib.BlockRelated) owners;
mapping(bytes32 => BlockLib.BlockRelated) proofs;
}
mapping(address => Account) private accounts;
event AccountOwnerAdded(
address account,
address owner
);
event AccountOwnerRemoved(
address account,
address owner
);
event AccountProofAdded(
address account,
bytes32 hash
);
event AccountProofRemoved(
address account,
bytes32 hash
);
function addAccountOwner(
address owner
)
external
{
require(
owner != address(0),
"ExternalAccountRegistry: cannot add 0x0 owner"
);
require(
!accounts[msg.sender].owners[owner].verifyAtCurrentBlock(),
"ExternalAccountRegistry: owner already exists"
);
accounts[msg.sender].owners[owner].added = true;
accounts[msg.sender].owners[owner].removedAtBlockNumber = 0;
emit AccountOwnerAdded(
msg.sender,
owner
);
}
function removeAccountOwner(
address owner
)
external
{
require(
accounts[msg.sender].owners[owner].verifyAtCurrentBlock(),
"ExternalAccountRegistry: owner doesn't exist"
);
accounts[msg.sender].owners[owner].removedAtBlockNumber = block.number;
emit AccountOwnerRemoved(
msg.sender,
owner
);
}
function addAccountProof(
bytes32 hash
)
external
{
require(
!accounts[msg.sender].proofs[hash].verifyAtCurrentBlock(),
"ExternalAccountRegistry: proof already exists"
);
accounts[msg.sender].proofs[hash].added = true;
accounts[msg.sender].proofs[hash].removedAtBlockNumber = 0;
emit AccountProofAdded(
msg.sender,
hash
);
}
function removeAccountProof(
bytes32 hash
)
external
{
require(
accounts[msg.sender].proofs[hash].verifyAtCurrentBlock(),
"ExternalAccountRegistry: proof doesn't exist"
);
accounts[msg.sender].proofs[hash].removedAtBlockNumber = block.number;
emit AccountProofRemoved(
msg.sender,
hash
);
}
function verifyAccountOwner(
address account,
address owner
)
external
view
returns (bool)
{
return accounts[account].owners[owner].verifyAtCurrentBlock();
}
function verifyAccountOwnerAtBlock(
address account,
address owner,
uint256 blockNumber
)
external
view
returns (bool)
{
return accounts[account].owners[owner].verifyAtBlock(blockNumber);
}
function verifyAccountProof(
address account,
bytes32 hash
)
external
view
returns (bool)
{
return accounts[account].proofs[hash].verifyAtCurrentBlock();
}
function verifyAccountProofAtBlock(
address account,
bytes32 hash,
uint256 blockNumber
)
external
view
returns (bool)
{
return accounts[account].proofs[hash].verifyAtBlock(blockNumber);
}
}
文件 12 的 20:GatewayRecipient.sol
pragma solidity ^0.6.12;
import "../common/libs/BytesLib.sol";
contract GatewayRecipient {
using BytesLib for bytes;
address public gateway;
constructor() internal {}
function _initializeGatewayRecipient(
address gateway_
)
internal
{
gateway = gateway_;
}
function _getContextAccount()
internal
view
returns (address)
{
return _getContextAddress(40);
}
function _getContextSender()
internal
view
returns (address)
{
return _getContextAddress(20);
}
function _getContextData()
internal
view
returns (bytes calldata)
{
bytes calldata result;
if (_isGatewaySender()) {
result = msg.data[:msg.data.length - 40];
} else {
result = msg.data;
}
return result;
}
function _getContextAddress(
uint256 offset
)
private
view
returns (address)
{
address result = address(0);
if (_isGatewaySender()) {
uint from = msg.data.length - offset;
result = bytes(msg.data[from:from + 20]).toAddress();
} else {
result = msg.sender;
}
return result;
}
function _isGatewaySender()
private
view
returns (bool)
{
bool result;
if (msg.sender == gateway) {
require(
msg.data.length >= 44,
"GatewayRecipient: invalid msg.data"
);
result = true;
}
return result;
}
}
文件 13 的 20:Guarded.sol
pragma solidity ^0.6.12;
import "../libs/ECDSALib.sol";
contract Guarded {
using ECDSALib for bytes32;
mapping(address => bool) private guardians;
event GuardianAdded(
address sender,
address guardian
);
event GuardianRemoved(
address sender,
address guardian
);
modifier onlyGuardian() {
require(
guardians[tx.origin],
"Guarded: tx.origin is not the guardian"
);
_;
}
constructor() internal {}
function addGuardian(
address guardian
)
external
onlyGuardian
{
_addGuardian(guardian);
}
function removeGuardian(
address guardian
)
external
onlyGuardian
{
require(
tx.origin != guardian,
"Guarded: cannot remove self"
);
require(
guardians[guardian],
"Guarded: guardian doesn't exist"
);
guardians[guardian] = false;
emit GuardianRemoved(
tx.origin,
guardian
);
}
function isGuardian(
address guardian
)
external
view
returns (bool)
{
return guardians[guardian];
}
function verifyGuardianSignature(
bytes32 messageHash,
bytes calldata signature
)
external
view
returns (bool)
{
return _verifyGuardianSignature(
messageHash,
signature
);
}
function _initializeGuarded(
address[] memory guardians_
)
internal
{
if (guardians_.length == 0) {
_addGuardian(tx.origin);
} else {
uint guardiansLen = guardians_.length;
for (uint i = 0; i < guardiansLen; i++) {
_addGuardian(guardians_[i]);
}
}
}
function _verifyGuardianSignature(
bytes32 messageHash,
bytes memory signature
)
internal
view
returns (bool)
{
address guardian = messageHash.recoverAddress(signature);
return guardians[guardian];
}
function _addGuardian(
address guardian
)
private
{
require(
guardian != address(0),
"Guarded: cannot add 0x0 guardian"
);
require(
!guardians[guardian],
"Guarded: guardian already exists"
);
guardians[guardian] = true;
emit GuardianAdded(
tx.origin,
guardian
);
}
}
文件 14 的 20:Initializable.sol
pragma solidity ^0.6.12;
contract Initializable {
address private initializer;
event Initialized(
address initializer
);
modifier onlyInitializer() {
require(
tx.origin == initializer,
"Initializable: tx.origin is not the initializer"
);
initializer = address(0);
_;
emit Initialized(
tx.origin
);
}
constructor()
internal
{
initializer = tx.origin;
}
function isInitialized()
external
view
returns (bool)
{
return initializer == address(0);
}
}
文件 15 的 20:PaymentDepositAccount.sol
pragma solidity ^0.6.12;
import "../common/access/Controlled.sol";
contract PaymentDepositAccount is Controlled {
constructor() public payable Controlled() {}
receive()
external
payable
{
}
function executeTransaction(
address to,
uint256 value,
bytes calldata data
)
external
onlyController
returns (bytes memory)
{
bytes memory result;
bool succeeded;
(succeeded, result) = payable(to).call{value: value}(data);
require(
succeeded,
"Account: transaction reverted"
);
return result;
}
}
文件 16 的 20:PaymentRegistry.sol
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;
import "../common/access/Guarded.sol";
import "../common/libs/ECDSALib.sol";
import "../common/libs/SafeMathLib.sol";
import "../common/lifecycle/Initializable.sol";
import "../common/signature/SignatureValidator.sol";
import "../common/token/ERC20Token.sol";
import "../external/ExternalAccountRegistry.sol";
import "../personal/PersonalAccountRegistry.sol";
import "../gateway/GatewayRecipient.sol";
import "./PaymentDepositAccount.sol";
contract PaymentRegistry is Guarded, Initializable, SignatureValidator, GatewayRecipient {
using ECDSALib for bytes32;
using SafeMathLib for uint256;
struct Deposit {
address account;
mapping(address => uint256) withdrawnAmount;
mapping(address => uint256) exitLockedUntil;
}
struct PaymentChannel {
uint256 committedAmount;
}
struct DepositWithdrawal {
address owner;
address token;
uint256 amount;
}
struct PaymentChannelCommit {
address sender;
address recipient;
address token;
bytes32 uid;
uint256 blockNumber;
uint256 amount;
}
uint256 private constant DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD = 28 days;
bytes32 private constant HASH_PREFIX_DEPOSIT_WITHDRAWAL = keccak256(
"DepositWithdrawal(address owner,address token,uint256 amount)"
);
bytes32 private constant HASH_PREFIX_PAYMENT_CHANNEL_COMMIT = keccak256(
"PaymentChannelCommit(address sender,address recipient,address token,bytes32 uid,uint256 blockNumber,uint256 amount)"
);
ExternalAccountRegistry public externalAccountRegistry;
PersonalAccountRegistry public personalAccountRegistry;
uint256 public depositExitLockPeriod;
mapping(address => Deposit) private deposits;
mapping(bytes32 => PaymentChannel) private paymentChannels;
event DepositAccountDeployed(
address depositAccount,
address owner
);
event DepositExitRequested(
address depositAccount,
address owner,
address token,
uint256 lockedUntil
);
event DepositExitCompleted(
address depositAccount,
address owner,
address token,
uint256 amount
);
event DepositExitRejected(
address depositAccount,
address owner,
address token
);
event DepositWithdrawn(
address depositAccount,
address owner,
address token,
uint256 amount
);
event PaymentChannelCommitted(
bytes32 hash,
address sender,
address recipient,
address token,
bytes32 uid,
uint256 amount
);
event PaymentWithdrawn(
bytes32 channelHash,
uint256 value
);
event PaymentDeposited(
bytes32 channelHash,
uint256 value
);
event PaymentSplit(
bytes32 channelHash,
uint256 totalValue,
uint256 depositValue
);
constructor() public Initializable() SignatureValidator() {}
function initialize(
ExternalAccountRegistry externalAccountRegistry_,
PersonalAccountRegistry personalAccountRegistry_,
uint256 depositExitLockPeriod_,
address[] calldata guardians_,
address gateway_
)
external
onlyInitializer
{
externalAccountRegistry = externalAccountRegistry_;
personalAccountRegistry = personalAccountRegistry_;
if (depositExitLockPeriod_ == 0) {
depositExitLockPeriod = DEFAULT_DEPOSIT_EXIT_LOCK_PERIOD;
} else {
depositExitLockPeriod = depositExitLockPeriod_;
}
_initializeGuarded(guardians_);
_initializeGatewayRecipient(gateway_);
}
function deployDepositAccount(
address owner
)
external
{
_deployDepositAccount(owner);
}
function requestDepositExit(
address token
)
external
{
address owner = _getContextAccount();
uint256 lockedUntil = deposits[owner].exitLockedUntil[token];
require(
lockedUntil == 0,
"PaymentRegistry: deposit exit already requested"
);
_deployDepositAccount(owner);
lockedUntil = now.add(depositExitLockPeriod);
deposits[owner].exitLockedUntil[token] = lockedUntil;
emit DepositExitRequested(
deposits[owner].account,
owner,
token,
lockedUntil
);
}
function processDepositExit(
address token
)
external
{
address owner = _getContextAccount();
uint256 lockedUntil = deposits[owner].exitLockedUntil[token];
require(
lockedUntil != 0,
"PaymentRegistry: deposit exit not requested"
);
require(
lockedUntil <= now,
"PaymentRegistry: deposit exit locked"
);
deposits[owner].exitLockedUntil[token] = 0;
address depositAccount = deposits[owner].account;
uint256 depositValue;
if (token == address(0)) {
depositValue = depositAccount.balance;
} else {
depositValue = ERC20Token(token).balanceOf(depositAccount);
}
_transferFromDeposit(
depositAccount,
owner,
token,
depositValue
);
emit DepositExitCompleted(
depositAccount,
owner,
token,
depositValue
);
}
function withdrawDeposit(
address token,
uint256 amount,
bytes calldata guardianSignature
)
external
{
address owner = _getContextAccount();
uint256 value = amount.sub(deposits[owner].withdrawnAmount[token]);
require(
value > 0,
"PaymentRegistry: invalid amount"
);
bytes32 messageHash = _hashDepositWithdrawal(
owner,
token,
amount
);
require(
_verifyGuardianSignature(messageHash, guardianSignature),
"PaymentRegistry: invalid guardian signature"
);
deposits[owner].withdrawnAmount[token] = amount;
_verifyDepositExitOrDeployAccount(owner, token);
_transferFromDeposit(
deposits[owner].account,
owner,
token,
value
);
emit DepositWithdrawn(
deposits[owner].account,
owner,
token,
amount
);
}
function commitPaymentChannelAndWithdraw(
address sender,
address token,
bytes32 uid,
uint256 blockNumber,
uint256 amount,
bytes calldata senderSignature,
bytes calldata guardianSignature
)
external
{
address recipient = _getContextAccount();
(bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(
sender,
recipient,
token,
uid,
blockNumber,
amount,
senderSignature,
guardianSignature
);
_transferFromDeposit(
depositAccount,
recipient,
token,
paymentValue
);
emit PaymentWithdrawn(hash, paymentValue);
}
function commitPaymentChannelAndDeposit(
address sender,
address token,
bytes32 uid,
uint256 blockNumber,
uint256 amount,
bytes calldata senderSignature,
bytes calldata guardianSignature
)
external
{
address recipient = _getContextAccount();
(bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(
sender,
recipient,
token,
uid,
blockNumber,
amount,
senderSignature,
guardianSignature
);
_transferFromDeposit(
depositAccount,
_computeDepositAccountAddress(recipient),
token,
paymentValue
);
emit PaymentDeposited(hash, paymentValue);
}
function commitPaymentChannelAndSplit(
address sender,
address token,
bytes32 uid,
uint256 blockNumber,
uint256 amount,
uint256 depositPaymentValue,
bytes calldata senderSignature,
bytes calldata guardianSignature
)
external
{
address recipient = _getContextAccount();
(bytes32 hash, address depositAccount, uint256 paymentValue) = _commitPaymentChannel(
sender,
recipient,
token,
uid,
blockNumber,
amount,
senderSignature,
guardianSignature
);
_transferSplitFromDeposit(
depositAccount,
recipient,
token,
paymentValue,
depositPaymentValue
);
emit PaymentSplit(hash, paymentValue, depositPaymentValue);
}
function computeDepositAccountAddress(
address owner
)
external
view
returns (address)
{
return _computeDepositAccountAddress(owner);
}
function isDepositAccountDeployed(
address owner
)
external
view
returns (bool)
{
return deposits[owner].account != address(0);
}
function getDepositExitLockedUntil(
address owner,
address token
)
external
view
returns (uint256)
{
return deposits[owner].exitLockedUntil[token];
}
function getDepositWithdrawnAmount(
address owner,
address token
)
external
view
returns (uint256)
{
return deposits[owner].withdrawnAmount[token];
}
function getPaymentChannelCommittedAmount(
bytes32 hash
)
external
view
returns (uint256)
{
return paymentChannels[hash].committedAmount;
}
function computePaymentChannelHash(
address sender,
address recipient,
address token,
bytes32 uid
)
external
pure
returns (bytes32)
{
return _computePaymentChannelHash(
sender,
recipient,
token,
uid
);
}
function hashDepositWithdrawal(
DepositWithdrawal memory depositWithdrawal
)
public
view
returns (bytes32)
{
return _hashDepositWithdrawal(
depositWithdrawal.owner,
depositWithdrawal.token,
depositWithdrawal.amount
);
}
function hashPaymentChannelCommit(
PaymentChannelCommit memory paymentChannelCommit
)
public
view
returns (bytes32)
{
return _hashPaymentChannelCommit(
paymentChannelCommit.sender,
paymentChannelCommit.recipient,
paymentChannelCommit.token,
paymentChannelCommit.uid,
paymentChannelCommit.blockNumber,
paymentChannelCommit.amount
);
}
function _deployDepositAccount(
address owner
)
private
{
if (deposits[owner].account == address(0)) {
bytes32 salt = keccak256(
abi.encodePacked(
owner
)
);
deposits[owner].account = address(new PaymentDepositAccount{salt: salt}());
emit DepositAccountDeployed(
deposits[owner].account,
owner
);
}
}
function _verifyDepositExitOrDeployAccount(
address owner,
address token
)
private
{
if (deposits[owner].exitLockedUntil[token] > 0) {
deposits[owner].exitLockedUntil[token] = 0;
emit DepositExitRejected(
deposits[owner].account,
owner,
token
);
} else {
_deployDepositAccount(owner);
}
}
function _commitPaymentChannel(
address sender,
address recipient,
address token,
bytes32 uid,
uint256 blockNumber,
uint256 amount,
bytes memory senderSignature,
bytes memory guardianSignature
)
private
returns (bytes32 hash, address depositAccount, uint256 paymentValue)
{
bytes32 messageHash = _hashPaymentChannelCommit(
sender,
recipient,
token,
uid,
blockNumber,
amount
);
if (senderSignature.length == 0) {
require(
externalAccountRegistry.verifyAccountProofAtBlock(sender, messageHash, blockNumber),
"PaymentRegistry: invalid guardian signature"
);
} else {
address signer = messageHash.recoverAddress(senderSignature);
if (sender != signer) {
require(
personalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber) ||
externalAccountRegistry.verifyAccountOwnerAtBlock(sender, signer, blockNumber),
"PaymentRegistry: invalid sender signature"
);
}
}
require(
_verifyGuardianSignature(messageHash, guardianSignature),
"PaymentRegistry: invalid guardian signature"
);
hash = _computePaymentChannelHash(
sender,
recipient,
token,
uid
);
paymentValue = amount.sub(paymentChannels[hash].committedAmount);
require(
paymentValue != 0,
"PaymentRegistry: invalid payment value"
);
paymentChannels[hash].committedAmount = amount;
_verifyDepositExitOrDeployAccount(sender, token);
depositAccount = deposits[sender].account;
emit PaymentChannelCommitted(
hash,
sender,
recipient,
token,
uid,
amount
);
return (hash, depositAccount, paymentValue);
}
function _transferFromDeposit(
address depositAccount,
address to,
address token,
uint256 value
)
private
{
if (token == address(0)) {
PaymentDepositAccount(payable(depositAccount)).executeTransaction(
to,
value,
new bytes(0)
);
} else {
bytes memory response = PaymentDepositAccount(payable(depositAccount)).executeTransaction(
token,
0,
abi.encodeWithSelector(
ERC20Token(token).transfer.selector,
to,
value
)
);
if (response.length > 0) {
require(
abi.decode(response, (bool)),
"PaymentRegistry: ERC20Token transfer reverted"
);
}
}
}
function _transferSplitFromDeposit(
address depositAccount,
address to,
address token,
uint256 paymentValue,
uint256 depositValue
)
private
{
require(
depositValue > 0,
"PaymentRegistry: invalid deposit value"
);
uint256 withdrawValue = paymentValue.sub(depositValue);
require(
withdrawValue > 0,
"PaymentRegistry: invalid withdraw value"
);
_transferFromDeposit(
depositAccount,
to,
token,
withdrawValue
);
_transferFromDeposit(
depositAccount,
_computeDepositAccountAddress(to),
token,
depositValue
);
}
function _computeDepositAccountAddress(
address owner
)
private
view
returns (address)
{
bytes32 salt = keccak256(
abi.encodePacked(
owner
)
);
bytes memory creationCode = type(PaymentDepositAccount).creationCode;
bytes32 data = keccak256(
abi.encodePacked(
bytes1(0xff),
address(this),
salt,
keccak256(creationCode)
)
);
return address(uint160(uint256(data)));
}
function _hashDepositWithdrawal(
address owner,
address token,
uint256 amount
)
private
view
returns (bytes32)
{
return _hashMessagePayload(HASH_PREFIX_DEPOSIT_WITHDRAWAL, abi.encodePacked(
owner,
token,
amount
));
}
function _hashPaymentChannelCommit(
address sender,
address recipient,
address token,
bytes32 uid,
uint256 blockNumber,
uint256 amount
)
private
view
returns (bytes32)
{
return _hashMessagePayload(HASH_PREFIX_PAYMENT_CHANNEL_COMMIT, abi.encodePacked(
sender,
recipient,
token,
uid,
blockNumber,
amount
));
}
function _computePaymentChannelHash(
address sender,
address recipient,
address token,
bytes32 uid
)
private
pure
returns (bytes32)
{
return keccak256(
abi.encodePacked(
sender,
recipient,
token,
uid
)
);
}
}
文件 17 的 20:PersonalAccountRegistry.sol
pragma solidity ^0.6.12;
import "../common/access/Guarded.sol";
import "../common/account/AccountController.sol";
import "../common/account/AccountRegistry.sol";
import "../common/libs/BlockLib.sol";
import "../common/libs/ECDSALib.sol";
import "../common/libs/ECDSAExtendedLib.sol";
import "../common/libs/SafeMathLib.sol";
import "../common/lifecycle/Initializable.sol";
import "../common/token/ERC20Token.sol";
import "../gateway/GatewayRecipient.sol";
contract PersonalAccountRegistry is Guarded, AccountController, AccountRegistry, Initializable, GatewayRecipient {
using BlockLib for BlockLib.BlockRelated;
using SafeMathLib for uint256;
using ECDSALib for bytes32;
using ECDSAExtendedLib for bytes;
struct Account {
bool deployed;
bytes32 salt;
mapping(address => BlockLib.BlockRelated) owners;
}
mapping(address => Account) private accounts;
event AccountOwnerAdded(
address account,
address owner
);
event AccountOwnerRemoved(
address account,
address owner
);
event AccountCallRefunded(
address account,
address beneficiary,
address token,
uint256 value
);
constructor() public Initializable() {}
function initialize(
address[] calldata guardians_,
address accountImplementation_,
address gateway_
)
external
onlyInitializer
{
_initializeGuarded(guardians_);
_initializeAccountController(address(this), accountImplementation_);
_initializeGatewayRecipient(gateway_);
}
function upgrade(
address accountImplementation_
)
external
onlyGuardian
{
_setAccountImplementation(accountImplementation_, true);
}
function deployAccount(
address account
)
external
{
_verifySender(account);
_deployAccount(account);
}
function upgradeAccount(
address account
)
external
{
_verifySender(account);
_upgradeAccount(account, true);
}
function addAccountOwner(
address account,
address owner
)
external
{
_verifySender(account);
require(
owner != address(0),
"PersonalAccountRegistry: cannot add 0x0 owner"
);
require(
!accounts[account].owners[owner].verifyAtCurrentBlock(),
"PersonalAccountRegistry: owner already exists"
);
accounts[account].owners[owner].added = true;
accounts[account].owners[owner].removedAtBlockNumber = 0;
emit AccountOwnerAdded(
account,
owner
);
}
function removeAccountOwner(
address account,
address owner
)
external
{
address sender = _verifySender(account);
require(
owner != sender,
"PersonalAccountRegistry: cannot remove self"
);
require(
accounts[account].owners[owner].verifyAtCurrentBlock(),
"PersonalAccountRegistry: owner doesn't exist"
);
accounts[account].owners[owner].removedAtBlockNumber = block.number;
emit AccountOwnerRemoved(
account,
owner
);
}
function executeAccountTransaction(
address account,
address to,
uint256 value,
bytes calldata data
)
external
{
_verifySender(account);
_deployAccount(account);
_executeAccountTransaction(
account,
to,
value,
data,
true
);
}
function refundAccountCall(
address account,
address token,
uint256 value
)
external
{
_verifySender(account);
_deployAccount(account);
if (token == address(0)) {
_executeAccountTransaction(
account,
tx.origin,
value,
new bytes(0),
false
);
} else {
bytes memory response = _executeAccountTransaction(
account,
token,
0,
abi.encodeWithSelector(
ERC20Token(token).transfer.selector,
tx.origin,
value
),
false
);
if (response.length > 0) {
require(
abi.decode(response, (bool)),
"PersonalAccountRegistry: ERC20Token transfer reverted"
);
}
}
emit AccountCallRefunded(
account,
tx.origin,
token,
value
);
}
function computeAccountAddress(
address saltOwner
)
external
view
returns (address)
{
return _computeAccountAddress(saltOwner);
}
function isAccountDeployed(
address account
)
external
view
returns (bool)
{
return accounts[account].deployed;
}
function verifyAccountOwner(
address account,
address owner
)
external
view
returns (bool)
{
return _verifyAccountOwner(account, owner);
}
function verifyAccountOwnerAtBlock(
address account,
address owner,
uint256 blockNumber
)
external
view
returns (bool)
{
bool result = false;
if (_verifyAccountOwner(account, owner)) {
result = true;
} else {
result = accounts[account].owners[owner].verifyAtBlock(blockNumber);
}
return result;
}
function isValidAccountSignature(
address account,
bytes32 messageHash,
bytes calldata signature
)
override
external
view
returns (bool)
{
return _verifyAccountOwner(
account,
messageHash.recoverAddress(signature)
);
}
function isValidAccountSignature(
address account,
bytes calldata message,
bytes calldata signature
)
override
external
view
returns (bool)
{
return _verifyAccountOwner(
account,
message.toEthereumSignedMessageHash().recoverAddress(signature)
);
}
function _verifySender(
address account
)
private
returns (address)
{
address sender = _getContextSender();
if (accounts[account].owners[sender].added) {
require(
accounts[account].owners[sender].removedAtBlockNumber == 0,
"PersonalAccountRegistry: sender is not the account owner"
);
} else {
require(
accounts[account].salt == 0,
"PersonalAccountRegistry: sender is not the account owner"
);
bytes32 salt = keccak256(
abi.encodePacked(sender)
);
require(
account == _computeAccountAddress(salt),
"PersonalAccountRegistry: sender is not the account owner"
);
accounts[account].salt = salt;
accounts[account].owners[sender].added = true;
emit AccountOwnerAdded(
account,
sender
);
}
return sender;
}
function _deployAccount(
address account
)
internal
{
if (!accounts[account].deployed) {
_deployAccount(
accounts[account].salt,
true
);
accounts[account].deployed = true;
}
}
function _computeAccountAddress(
address saltOwner
)
private
view
returns (address)
{
bytes32 salt = keccak256(
abi.encodePacked(saltOwner)
);
return _computeAccountAddress(salt);
}
function _verifyAccountOwner(
address account,
address owner
)
private
view
returns (bool)
{
bool result;
if (accounts[account].owners[owner].added) {
result = accounts[account].owners[owner].removedAtBlockNumber == 0;
} else if (accounts[account].salt == 0) {
result = account == _computeAccountAddress(owner);
}
return result;
}
}
文件 18 的 20:SafeMathLib.sol
pragma solidity ^0.6.12;
library SafeMathLib {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMathLib: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMathLib: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMathLib: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMathLib: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMathLib: modulo by zero");
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
文件 19 的 20:SignatureValidator.sol
pragma solidity ^0.6.12;
import "../libs/ECDSALib.sol";
contract SignatureValidator {
using ECDSALib for bytes32;
uint256 public chainId;
constructor() internal {
uint256 chainId_;
assembly {
chainId_ := chainid()
}
chainId = chainId_;
}
function _hashMessagePayload(
bytes32 messagePrefix,
bytes memory messagePayload
)
internal
view
returns (bytes32)
{
return keccak256(abi.encodePacked(
chainId,
address(this),
messagePrefix,
messagePayload
)).toEthereumSignedMessageHash();
}
}
文件 20 的 20:StringsLib.sol
pragma solidity ^0.6.12;
library StringsLib {
function toString(
uint256 value
)
internal
pure
returns (string memory)
{
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
uint256 index = digits - 1;
temp = value;
while (temp != 0) {
buffer[index--] = byte(uint8(48 + temp % 10));
temp /= 10;
}
return string(buffer);
}
}
{
"compilationTarget": {
"src/payments/PaymentRegistry.sol": "PaymentRegistry"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "none",
"useLiteralContent": true
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"depositAccount","type":"address"},{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"DepositAccountDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"depositAccount","type":"address"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositExitCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"depositAccount","type":"address"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"DepositExitRejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"depositAccount","type":"address"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"lockedUntil","type":"uint256"}],"name":"DepositExitRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"depositAccount","type":"address"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DepositWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"guardian","type":"address"}],"name":"GuardianAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"guardian","type":"address"}],"name":"GuardianRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"initializer","type":"address"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"hash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bytes32","name":"uid","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PaymentChannelCommitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"channelHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"PaymentDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"channelHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"totalValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositValue","type":"uint256"}],"name":"PaymentSplit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"channelHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"PaymentWithdrawn","type":"event"},{"inputs":[{"internalType":"address","name":"guardian","type":"address"}],"name":"addGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"senderSignature","type":"bytes"},{"internalType":"bytes","name":"guardianSignature","type":"bytes"}],"name":"commitPaymentChannelAndDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"depositPaymentValue","type":"uint256"},{"internalType":"bytes","name":"senderSignature","type":"bytes"},{"internalType":"bytes","name":"guardianSignature","type":"bytes"}],"name":"commitPaymentChannelAndSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"senderSignature","type":"bytes"},{"internalType":"bytes","name":"guardianSignature","type":"bytes"}],"name":"commitPaymentChannelAndWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"computeDepositAccountAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"uid","type":"bytes32"}],"name":"computePaymentChannelHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"deployDepositAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositExitLockPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"externalAccountRegistry","outputs":[{"internalType":"contract ExternalAccountRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gateway","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"getDepositExitLockedUntil","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"token","type":"address"}],"name":"getDepositWithdrawnAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"}],"name":"getPaymentChannelCommittedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct PaymentRegistry.DepositWithdrawal","name":"depositWithdrawal","type":"tuple"}],"name":"hashDepositWithdrawal","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"uid","type":"bytes32"},{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct PaymentRegistry.PaymentChannelCommit","name":"paymentChannelCommit","type":"tuple"}],"name":"hashPaymentChannelCommit","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ExternalAccountRegistry","name":"externalAccountRegistry_","type":"address"},{"internalType":"contract PersonalAccountRegistry","name":"personalAccountRegistry_","type":"address"},{"internalType":"uint256","name":"depositExitLockPeriod_","type":"uint256"},{"internalType":"address[]","name":"guardians_","type":"address[]"},{"internalType":"address","name":"gateway_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"isDepositAccountDeployed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"guardian","type":"address"}],"name":"isGuardian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"personalAccountRegistry","outputs":[{"internalType":"contract PersonalAccountRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"processDepositExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guardian","type":"address"}],"name":"removeGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"requestDepositExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"messageHash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"verifyGuardianSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"guardianSignature","type":"bytes"}],"name":"withdrawDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"}]