Diff
checker
テキスト
テキスト
画像
ドキュメント
Excel
フォルダ
Legal
Enterprise
デスクトップ
料金
ログイン
Diffchecker デスクトップのダウンロード
テキスト比較
2 つのテキスト ファイルの違いを見つける
ツール
履歴
表示
レイアウト
分割
統合
ライブエディター
空白の変更を非表示
未変更行を折りたたむ
折り返しなし
比較精度
スマート
構文
なし
外観を変更
処理
無視
テキスト変換
最初の差分へ移動
入力を編集
Diffchecker Desktop
Diffcheckerを実行する最も安全な方法。Diffchecker Desktopアプリを入手:あなたの差分はコンピューターから出ることはありません!
Desktopを入手
この比較の残りの部分を読み込んでいます。
Diff between PyUSD implementation 1 and current implementation
作成日
3 年前
差分は期限切れになりません
クリア
エクスポート
共有
説明
13 削除
行
合計
削除
文字
合計
削除
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
645 行
すべてコピー
13 追加
行
合計
追加
文字
合計
追加
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
644 行
すべてコピー
/**
/**
コピー
コピー済み
コピー
コピー済み
*Submitted for verification at Etherscan.io on 2023-
01-23
*Submitted for verification at Etherscan.io on 2023-
08-07
*/
*/
// File: contracts/zeppelin/SafeMath.sol
// File: contracts/zeppelin/SafeMath.sol
pragma solidity ^0.4.24;
pragma solidity ^0.4.24;
/**
/**
* @title SafeMath
* @title SafeMath
* @dev Math operations with safety checks that throw on error
* @dev Math operations with safety checks that throw on error
*/
*/
library SafeMath {
library SafeMath {
/**
/**
* @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
* @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
require(b <= a);
uint256 c = a - b;
uint256 c = a - b;
return c;
return c;
}
}
/**
/**
* @dev Adds two numbers, reverts on overflow.
* @dev Adds two numbers, reverts on overflow.
*/
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
uint256 c = a + b;
require(c >= a);
require(c >= a);
return c;
return c;
}
}
}
}
コピー
コピー済み
コピー
コピー済み
// File: contracts/
XYZ
Implementation.sol
// File: contracts/
PYUSD
Implementation.sol
pragma solidity ^0.4.24;
pragma solidity ^0.4.24;
pragma experimental "v0.5.0";
pragma experimental "v0.5.0";
/**
/**
コピー
コピー済み
コピー
コピー済み
* @title
XYZ
Implementation
* @title
PYUSD
Implementation
* @dev this contract is a Pausable ERC20 token with Burn and Mint
* @dev this contract is a Pausable ERC20 token with Burn and Mint
コピー
コピー済み
コピー
コピー済み
* controlled by a central SupplyController. By implementing
XYZ
Implementation
* controlled by a central SupplyController. By implementing
PYUSD
Implementation
* this contract also includes external methods for setting
* this contract also includes external methods for setting
* a new implementation contract for the Proxy.
* a new implementation contract for the Proxy.
* NOTE: The storage defined here will actually be held in the Proxy
* NOTE: The storage defined here will actually be held in the Proxy
* contract and all calls to this contract should be made through
* contract and all calls to this contract should be made through
* the proxy, including admin actions done as owner or supplyController.
* the proxy, including admin actions done as owner or supplyController.
* Any call to transfer against this contract should fail
* Any call to transfer against this contract should fail
* with insufficient funds since no tokens will be issued there.
* with insufficient funds since no tokens will be issued there.
*/
*/
コピー
コピー済み
コピー
コピー済み
contract
XYZ
Implementation {
contract
PYUSD
Implementation {
/**
/**
* MATH
* MATH
*/
*/
using SafeMath for uint256;
using SafeMath for uint256;
/**
/**
* DATA
* DATA
*/
*/
// INITIALIZATION DATA
// INITIALIZATION DATA
bool private initialized;
bool private initialized;
// ERC20 BASIC DATA
// ERC20 BASIC DATA
mapping(address => uint256) internal balances;
mapping(address => uint256) internal balances;
uint256 internal totalSupply_;
uint256 internal totalSupply_;
コピー
コピー済み
コピー
コピー済み
string public constant name = "
Hopper
"; // solium-disable-line
string public constant name = "
PayPal USD
"; // solium-disable-line
string public constant symbol = "
XYZ
"; // solium-disable-line uppercase
string public constant symbol = "
PYUSD
"; // solium-disable-line uppercase
uint8 public constant decimals = 6; // solium-disable-line uppercase
uint8 public constant decimals = 6; // solium-disable-line uppercase
// ERC20 DATA
// ERC20 DATA
mapping(address => mapping(address => uint256)) internal allowed;
mapping(address => mapping(address => uint256)) internal allowed;
// OWNER DATA PART 1
// OWNER DATA PART 1
address public owner;
address public owner;
// PAUSABILITY DATA
// PAUSABILITY DATA
bool public paused;
bool public paused;
// ASSET PROTECTION DATA
// ASSET PROTECTION DATA
address public assetProtectionRole;
address public assetProtectionRole;
mapping(address => bool) internal frozen;
mapping(address => bool) internal frozen;
// SUPPLY CONTROL DATA
// SUPPLY CONTROL DATA
address public supplyController;
address public supplyController;
// OWNER DATA PART 2
// OWNER DATA PART 2
address public proposedOwner;
address public proposedOwner;
// DELEGATED TRANSFER DATA
// DELEGATED TRANSFER DATA
address public betaDelegateWhitelister;
address public betaDelegateWhitelister;
mapping(address => bool) internal betaDelegateWhitelist;
mapping(address => bool) internal betaDelegateWhitelist;
mapping(address => uint256) internal nextSeqs;
mapping(address => uint256) internal nextSeqs;
// EIP191 header for EIP712 prefix
// EIP191 header for EIP712 prefix
string constant internal EIP191_HEADER = "\x19\x01";
string constant internal EIP191_HEADER = "\x19\x01";
保存された差分
原文
ファイルを開く
/** *Submitted for verification at Etherscan.io on 2023-01-23 */ // File: contracts/zeppelin/SafeMath.sol pragma solidity ^0.4.24; /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { /** * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a); uint256 c = a - b; return c; } /** * @dev Adds two numbers, reverts on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a); return c; } } // File: contracts/XYZImplementation.sol pragma solidity ^0.4.24; pragma experimental "v0.5.0"; /** * @title XYZImplementation * @dev this contract is a Pausable ERC20 token with Burn and Mint * controlled by a central SupplyController. By implementing XYZImplementation * this contract also includes external methods for setting * a new implementation contract for the Proxy. * NOTE: The storage defined here will actually be held in the Proxy * contract and all calls to this contract should be made through * the proxy, including admin actions done as owner or supplyController. * Any call to transfer against this contract should fail * with insufficient funds since no tokens will be issued there. */ contract XYZImplementation { /** * MATH */ using SafeMath for uint256; /** * DATA */ // INITIALIZATION DATA bool private initialized; // ERC20 BASIC DATA mapping(address => uint256) internal balances; uint256 internal totalSupply_; string public constant name = "Hopper"; // solium-disable-line string public constant symbol = "XYZ"; // solium-disable-line uppercase uint8 public constant decimals = 6; // solium-disable-line uppercase // ERC20 DATA mapping(address => mapping(address => uint256)) internal allowed; // OWNER DATA PART 1 address public owner; // PAUSABILITY DATA bool public paused; // ASSET PROTECTION DATA address public assetProtectionRole; mapping(address => bool) internal frozen; // SUPPLY CONTROL DATA address public supplyController; // OWNER DATA PART 2 address public proposedOwner; // DELEGATED TRANSFER DATA address public betaDelegateWhitelister; mapping(address => bool) internal betaDelegateWhitelist; mapping(address => uint256) internal nextSeqs; // EIP191 header for EIP712 prefix string constant internal EIP191_HEADER = "\x19\x01"; // Hash of the EIP712 Domain Separator Schema bytes32 constant internal EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256( "EIP712Domain(string name,address verifyingContract)" ); bytes32 constant internal EIP712_DELEGATED_TRANSFER_SCHEMA_HASH = keccak256( "BetaDelegatedTransfer(address to,uint256 value,uint256 fee,uint256 seq,uint256 deadline)" ); // Hash of the EIP712 Domain Separator data // solhint-disable-next-line var-name-mixedcase bytes32 public EIP712_DOMAIN_HASH; /** * EVENTS */ // ERC20 BASIC EVENTS event Transfer(address indexed from, address indexed to, uint256 value); // ERC20 EVENTS event Approval( address indexed owner, address indexed spender, uint256 value ); // OWNABLE EVENTS event OwnershipTransferProposed( address indexed currentOwner, address indexed proposedOwner ); event OwnershipTransferDisregarded( address indexed oldProposedOwner ); event OwnershipTransferred( address indexed oldOwner, address indexed newOwner ); // PAUSABLE EVENTS event Pause(); event Unpause(); // ASSET PROTECTION EVENTS event AddressFrozen(address indexed addr); event AddressUnfrozen(address indexed addr); event FrozenAddressWiped(address indexed addr); event AssetProtectionRoleSet ( address indexed oldAssetProtectionRole, address indexed newAssetProtectionRole ); // SUPPLY CONTROL EVENTS event SupplyIncreased(address indexed to, uint256 value); event SupplyDecreased(address indexed from, uint256 value); event SupplyControllerSet( address indexed oldSupplyController, address indexed newSupplyController ); // DELEGATED TRANSFER EVENTS event BetaDelegatedTransfer( address indexed from, address indexed to, uint256 value, uint256 seq, uint256 fee ); event BetaDelegateWhitelisterSet( address indexed oldWhitelister, address indexed newWhitelister ); event BetaDelegateWhitelisted(address indexed newDelegate); event BetaDelegateUnwhitelisted(address indexed oldDelegate); /** * FUNCTIONALITY */ // INITIALIZATION FUNCTIONALITY /** * @dev sets 0 initials tokens, the owner, and the supplyController. * this serves as the constructor for the proxy but compiles to the * memory model of the Implementation contract. */ function initialize() public { require(!initialized, "MANDATORY VERIFICATION REQUIRED: The proxy has already been initialized, verify the owner and supply controller addresses."); owner = msg.sender; assetProtectionRole = address(0); totalSupply_ = 0; supplyController = msg.sender; initializeDomainSeparator(); initialized = true; } /** * The constructor is used here to ensure that the implementation * contract is initialized. An uncontrolled implementation * contract might lead to misleading state * for users who accidentally interact with it. */ constructor() public { initialize(); pause(); } /** * @dev To be called when upgrading the contract using upgradeAndCall to add delegated transfers */ function initializeDomainSeparator() private { // hash the name context with the contract address EIP712_DOMAIN_HASH = keccak256(abi.encodePacked(// solium-disable-line EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH, keccak256(bytes(name)), bytes32(address(this)) )); } // ERC20 BASIC FUNCTIONALITY /** * @dev Total number of tokens in existence */ function totalSupply() public view returns (uint256) { return totalSupply_; } /** * @dev Transfer token to a specified address from msg.sender * Note: the use of Safemath ensures that _value is nonnegative. * @param _to The address to transfer to. * @param _value The amount to be transferred. */ function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) { require(_to != address(0), "cannot transfer to address zero"); require(!frozen[_to] && !frozen[msg.sender], "address frozen"); require(_value <= balances[msg.sender], "insufficient funds"); balances[msg.sender] = balances[msg.sender].sub(_value); balances[_to] = balances[_to].add(_value); emit Transfer(msg.sender, _to, _value); return true; } /** * @dev Gets the balance of the specified address. * @param _addr The address to query the the balance of. * @return An uint256 representing the amount owned by the passed address. */ function balanceOf(address _addr) public view returns (uint256) { return balances[_addr]; } // ERC20 FUNCTIONALITY /** * @dev Transfer tokens from one address to another * @param _from address The address which you want to send tokens from * @param _to address The address which you want to transfer to * @param _value uint256 the amount of tokens to be transferred */ function transferFrom( address _from, address _to, uint256 _value ) public whenNotPaused returns (bool) { require(_to != address(0), "cannot transfer to address zero"); require(!frozen[_to] && !frozen[_from] && !frozen[msg.sender], "address frozen"); require(_value <= balances[_from], "insufficient funds"); require(_value <= allowed[_from][msg.sender], "insufficient allowance"); balances[_from] = balances[_from].sub(_value); balances[_to] = balances[_to].add(_value); allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); emit Transfer(_from, _to, _value); return true; } /** * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. * Beware that changing an allowance with this method brings the risk that someone may use both the old * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * @param _spender The address which will spend the funds. * @param _value The amount of tokens to be spent. */ function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) { require(!frozen[_spender] && !frozen[msg.sender], "address frozen"); allowed[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); return true; } /** * @dev Increase the amount of tokens that an owner allowed to a spender. * * To increment allowed value is better to use this function to avoid 2 calls (and wait until the first transaction * is mined) instead of approve. * @param _spender The address which will spend the funds. * @param _addedValue The amount of tokens to increase the allowance by. */ function increaseApproval(address _spender, uint _addedValue) public whenNotPaused returns (bool) { require(!frozen[_spender] && !frozen[msg.sender], "address frozen"); allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue); emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } /** * @dev Decrease the amount of tokens that an owner allowed to a spender. * * To decrement allowed value is better to use this function to avoid 2 calls (and wait until the first transaction * is mined) instead of approve. * @param _spender The address which will spend the funds. * @param _subtractedValue The amount of tokens to decrease the allowance by. */ function decreaseApproval(address _spender, uint _subtractedValue) public whenNotPaused returns (bool) { require(!frozen[_spender] && !frozen[msg.sender], "address frozen"); uint oldValue = allowed[msg.sender][_spender]; if (_subtractedValue > oldValue) { allowed[msg.sender][_spender] = 0; } else { allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); } emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } /** * @dev Function to check the amount of tokens that an owner allowed to a spender. * @param _owner address The address which owns the funds. * @param _spender address The address which will spend the funds. * @return A uint256 specifying the amount of tokens still available for the spender. */ function allowance( address _owner, address _spender ) public view returns (uint256) { return allowed[_owner][_spender]; } // OWNER FUNCTIONALITY /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(msg.sender == owner, "onlyOwner"); _; } /** * @dev Allows the current owner to begin transferring control of the contract to a proposedOwner * @param _proposedOwner The address to transfer ownership to. */ function proposeOwner(address _proposedOwner) public onlyOwner { require(_proposedOwner != address(0), "cannot transfer ownership to address zero"); require(msg.sender != _proposedOwner, "caller already is owner"); proposedOwner = _proposedOwner; emit OwnershipTransferProposed(owner, proposedOwner); } /** * @dev Allows the current owner or proposed owner to cancel transferring control of the contract to a proposedOwner */ function disregardProposeOwner() public { require(msg.sender == proposedOwner || msg.sender == owner, "only proposedOwner or owner"); require(proposedOwner != address(0), "can only disregard a proposed owner that was previously set"); address _oldProposedOwner = proposedOwner; proposedOwner = address(0); emit OwnershipTransferDisregarded(_oldProposedOwner); } /** * @dev Allows the proposed owner to complete transferring control of the contract to the proposedOwner. */ function claimOwnership() public { require(msg.sender == proposedOwner, "onlyProposedOwner"); address _oldOwner = owner; owner = proposedOwner; proposedOwner = address(0); emit OwnershipTransferred(_oldOwner, owner); } /** * @dev Reclaim all XYZ at the contract address. * This sends the XYZ tokens that this contract add holding to the owner. * Note: this is not affected by freeze constraints. */ function reclaimXYZ() external onlyOwner { uint256 _balance = balances[this]; balances[this] = 0; balances[owner] = balances[owner].add(_balance); emit Transfer(this, owner, _balance); } // PAUSABILITY FUNCTIONALITY /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!paused, "whenNotPaused"); _; } /** * @dev called by the owner to pause, triggers stopped state */ function pause() public onlyOwner { require(!paused, "already paused"); paused = true; emit Pause(); } /** * @dev called by the owner to unpause, returns to normal state */ function unpause() public onlyOwner { require(paused, "already unpaused"); paused = false; emit Unpause(); } // ASSET PROTECTION FUNCTIONALITY /** * @dev Sets a new asset protection role address. * @param _newAssetProtectionRole The new address allowed to freeze/unfreeze addresses and seize their tokens. */ function setAssetProtectionRole(address _newAssetProtectionRole) public { require(msg.sender == assetProtectionRole || msg.sender == owner, "only assetProtectionRole or Owner"); require(assetProtectionRole != _newAssetProtectionRole, "new address is same as a current one"); emit AssetProtectionRoleSet(assetProtectionRole, _newAssetProtectionRole); assetProtectionRole = _newAssetProtectionRole; } modifier onlyAssetProtectionRole() { require(msg.sender == assetProtectionRole, "onlyAssetProtectionRole"); _; } /** * @dev Freezes an address balance from being transferred. * @param _addr The new address to freeze. */ function freeze(address _addr) public onlyAssetProtectionRole { require(!frozen[_addr], "address already frozen"); frozen[_addr] = true; emit AddressFrozen(_addr); } /** * @dev Unfreezes an address balance allowing transfer. * @param _addr The new address to unfreeze. */ function unfreeze(address _addr) public onlyAssetProtectionRole { require(frozen[_addr], "address already unfrozen"); frozen[_addr] = false; emit AddressUnfrozen(_addr); } /** * @dev Wipes the balance of a frozen address, burning the tokens * and setting the approval to zero. * @param _addr The new frozen address to wipe. */ function wipeFrozenAddress(address _addr) public onlyAssetProtectionRole { require(frozen[_addr], "address is not frozen"); uint256 _balance = balances[_addr]; balances[_addr] = 0; totalSupply_ = totalSupply_.sub(_balance); emit FrozenAddressWiped(_addr); emit SupplyDecreased(_addr, _balance); emit Transfer(_addr, address(0), _balance); } /** * @dev Gets whether the address is currently frozen. * @param _addr The address to check if frozen. * @return A bool representing whether the given address is frozen. */ function isFrozen(address _addr) public view returns (bool) { return frozen[_addr]; } // SUPPLY CONTROL FUNCTIONALITY /** * @dev Sets a new supply controller address. * @param _newSupplyController The address allowed to burn/mint tokens to control supply. */ function setSupplyController(address _newSupplyController) public { require(msg.sender == supplyController || msg.sender == owner, "only SupplyController or Owner"); require(_newSupplyController != address(0), "cannot set supply controller to address zero"); require(supplyController != _newSupplyController, "new address is same as a current one"); emit SupplyControllerSet(supplyController, _newSupplyController); supplyController = _newSupplyController; } modifier onlySupplyController() { require(msg.sender == supplyController, "onlySupplyController"); _; } /** * @dev Increases the total supply by minting the specified number of tokens to the supply controller account. * @param _value The number of tokens to add. * @return A boolean that indicates if the operation was successful. */ function increaseSupply(uint256 _value) public onlySupplyController returns (bool success) { totalSupply_ = totalSupply_.add(_value); balances[supplyController] = balances[supplyController].add(_value); emit SupplyIncreased(supplyController, _value); emit Transfer(address(0), supplyController, _value); return true; } /** * @dev Decreases the total supply by burning the specified number of tokens from the supply controller account. * @param _value The number of tokens to remove. * @return A boolean that indicates if the operation was successful. */ function decreaseSupply(uint256 _value) public onlySupplyController returns (bool success) { require(_value <= balances[supplyController], "not enough supply"); balances[supplyController] = balances[supplyController].sub(_value); totalSupply_ = totalSupply_.sub(_value); emit SupplyDecreased(supplyController, _value); emit Transfer(supplyController, address(0), _value); return true; } // DELEGATED TRANSFER FUNCTIONALITY /** * @dev returns the next seq for a target address. * The transactor must submit nextSeqOf(transactor) in the next transaction for it to be valid. * Note: that the seq context is specific to this smart contract. * @param target The target address. * @return the seq. */ // function nextSeqOf(address target) public view returns (uint256) { return nextSeqs[target]; } /** * @dev Performs a transfer on behalf of the from address, identified by its signature on the delegatedTransfer msg. * Splits a signature byte array into r,s,v for convenience. * @param sig the signature of the delgatedTransfer msg. * @param to The address to transfer to. * @param value The amount to be transferred. * @param fee an optional ERC20 fee paid to the executor of betaDelegatedTransfer by the from address. * @param seq a sequencing number included by the from address specific to this contract to protect from replays. * @param deadline a block number after which the pre-signed transaction has expired. * @return A boolean that indicates if the operation was successful. */ function betaDelegatedTransfer( bytes sig, address to, uint256 value, uint256 fee, uint256 seq, uint256 deadline ) public returns (bool) { require(sig.length == 65, "signature should have length 65"); bytes32 r; bytes32 s; uint8 v; assembly { r := mload(add(sig, 32)) s := mload(add(sig, 64)) v := byte(0, mload(add(sig, 96))) } _betaDelegatedTransfer(r, s, v, to, value, fee, seq, deadline); return true; } /** * @dev Performs a transfer on behalf of the from address, identified by its signature on the betaDelegatedTransfer msg. * Note: both the delegate and transactor sign in the fees. The transactor, however, * has no control over the gas price, and therefore no control over the transaction time. * Beta prefix chosen to avoid a name clash with an emerging standard in ERC865 or elsewhere. * Internal to the contract - see betaDelegatedTransfer and betaDelegatedTransferBatch. * @param r the r signature of the delgatedTransfer msg. * @param s the s signature of the delgatedTransfer msg. * @param v the v signature of the delgatedTransfer msg. * @param to The address to transfer to. * @param value The amount to be transferred. * @param fee an optional ERC20 fee paid to the delegate of betaDelegatedTransfer by the from address. * @param seq a sequencing number included by the from address specific to this contract to protect from replays. * @param deadline a block number after which the pre-signed transaction has expired. * @return A boolean that indicates if the operation was successful. */ function _betaDelegatedTransfer( bytes32 r, bytes32 s, uint8 v, address to, uint256 value, uint256 fee, uint256 seq, uint256 deadline ) internal whenNotPaused returns (bool) { require(betaDelegateWhitelist[msg.sender], "Beta feature only accepts whitelisted delegates"); require(value > 0 || fee > 0, "cannot transfer zero tokens with zero fee"); require(block.number <= deadline, "transaction expired"); // prevent sig malleability from ecrecover() require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "signature incorrect"); require(v == 27 || v == 28, "signature incorrect"); // EIP712 scheme: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md bytes32 delegatedTransferHash = keccak256(abi.encodePacked(// solium-disable-line EIP712_DELEGATED_TRANSFER_SCHEMA_HASH, bytes32(to), value, fee, seq, deadline )); bytes32 hash = keccak256(abi.encodePacked(EIP191_HEADER, EIP712_DOMAIN_HASH, delegatedTransferHash)); address _from = ecrecover(hash, v, r, s); require(_from != address(0), "error determining from address from signature"); require(to != address(0), "canno use address zero"); require(!frozen[to] && !frozen[_from] && !frozen[msg.sender], "address frozen"); require(value.add(fee) <= balances[_from], "insufficient fund"); require(nextSeqs[_from] == seq, "incorrect seq"); nextSeqs[_from] = nextSeqs[_from].add(1); balances[_from] = balances[_from].sub(value.add(fee)); if (fee != 0) { balances[msg.sender] = balances[msg.sender].add(fee); emit Transfer(_from, msg.sender, fee); } balances[to] = balances[to].add(value); emit Transfer(_from, to, value); emit BetaDelegatedTransfer(_from, to, value, seq, fee); return true; } /** * @dev Performs an atomic batch of transfers on behalf of the from addresses, identified by their signatures. * Lack of nested array support in arguments requires all arguments to be passed as equal size arrays where * delegated transfer number i is the combination of all arguments at index i * @param r the r signatures of the delgatedTransfer msg. * @param s the s signatures of the delgatedTransfer msg. * @param v the v signatures of the delgatedTransfer msg. * @param to The addresses to transfer to. * @param value The amounts to be transferred. * @param fee optional ERC20 fees paid to the delegate of betaDelegatedTransfer by the from address. * @param seq sequencing numbers included by the from address specific to this contract to protect from replays. * @param deadline block numbers after which the pre-signed transactions have expired. * @return A boolean that indicates if the operation was successful. */ function betaDelegatedTransferBatch( bytes32[] r, bytes32[] s, uint8[] v, address[] to, uint256[] value, uint256[] fee, uint256[] seq, uint256[] deadline ) public returns (bool) { require(r.length == s.length && r.length == v.length && r.length == to.length && r.length == value.length, "length mismatch"); require(r.length == fee.length && r.length == seq.length && r.length == deadline.length, "length mismatch"); for (uint i = 0; i < r.length; i++) { _betaDelegatedTransfer(r[i], s[i], v[i], to[i], value[i], fee[i], seq[i], deadline[i]); } return true; } /** * @dev Gets whether the address is currently whitelisted for betaDelegateTransfer. * @param _addr The address to check if whitelisted. * @return A bool representing whether the given address is whitelisted. */ function isWhitelistedBetaDelegate(address _addr) public view returns (bool) { return betaDelegateWhitelist[_addr]; } /** * @dev Sets a new betaDelegate whitelister. * @param _newWhitelister The address allowed to whitelist betaDelegates. */ function setBetaDelegateWhitelister(address _newWhitelister) public { require(msg.sender == betaDelegateWhitelister || msg.sender == owner, "only Whitelister or Owner"); require(betaDelegateWhitelister != _newWhitelister, "new address is same as a current one"); betaDelegateWhitelister = _newWhitelister; emit BetaDelegateWhitelisterSet(betaDelegateWhitelister, _newWhitelister); } modifier onlyBetaDelegateWhitelister() { require(msg.sender == betaDelegateWhitelister, "onlyBetaDelegateWhitelister"); _; } /** * @dev Whitelists an address to allow calling BetaDelegatedTransfer. * @param _addr The new address to whitelist. */ function whitelistBetaDelegate(address _addr) public onlyBetaDelegateWhitelister { require(!betaDelegateWhitelist[_addr], "delegate already whitelisted"); betaDelegateWhitelist[_addr] = true; emit BetaDelegateWhitelisted(_addr); } /** * @dev Unwhitelists an address to disallow calling BetaDelegatedTransfer. * @param _addr The new address to whitelist. */ function unwhitelistBetaDelegate(address _addr) public onlyBetaDelegateWhitelister { require(betaDelegateWhitelist[_addr], "delegate not whitelisted"); betaDelegateWhitelist[_addr] = false; emit BetaDelegateUnwhitelisted(_addr); } }
変更されたテキスト
ファイルを開く
/** *Submitted for verification at Etherscan.io on 2023-08-07 */ // File: contracts/zeppelin/SafeMath.sol pragma solidity ^0.4.24; /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { /** * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a); uint256 c = a - b; return c; } /** * @dev Adds two numbers, reverts on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a); return c; } } // File: contracts/PYUSDImplementation.sol pragma solidity ^0.4.24; pragma experimental "v0.5.0"; /** * @title PYUSDImplementation * @dev this contract is a Pausable ERC20 token with Burn and Mint * controlled by a central SupplyController. By implementing PYUSDImplementation * this contract also includes external methods for setting * a new implementation contract for the Proxy. * NOTE: The storage defined here will actually be held in the Proxy * contract and all calls to this contract should be made through * the proxy, including admin actions done as owner or supplyController. * Any call to transfer against this contract should fail * with insufficient funds since no tokens will be issued there. */ contract PYUSDImplementation { /** * MATH */ using SafeMath for uint256; /** * DATA */ // INITIALIZATION DATA bool private initialized; // ERC20 BASIC DATA mapping(address => uint256) internal balances; uint256 internal totalSupply_; string public constant name = "PayPal USD"; // solium-disable-line string public constant symbol = "PYUSD"; // solium-disable-line uppercase uint8 public constant decimals = 6; // solium-disable-line uppercase // ERC20 DATA mapping(address => mapping(address => uint256)) internal allowed; // OWNER DATA PART 1 address public owner; // PAUSABILITY DATA bool public paused; // ASSET PROTECTION DATA address public assetProtectionRole; mapping(address => bool) internal frozen; // SUPPLY CONTROL DATA address public supplyController; // OWNER DATA PART 2 address public proposedOwner; // DELEGATED TRANSFER DATA address public betaDelegateWhitelister; mapping(address => bool) internal betaDelegateWhitelist; mapping(address => uint256) internal nextSeqs; // EIP191 header for EIP712 prefix string constant internal EIP191_HEADER = "\x19\x01"; // Hash of the EIP712 Domain Separator Schema bytes32 constant internal EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH = keccak256( "EIP712Domain(string name,address verifyingContract)" ); bytes32 constant internal EIP712_DELEGATED_TRANSFER_SCHEMA_HASH = keccak256( "BetaDelegatedTransfer(address to,uint256 value,uint256 fee,uint256 seq,uint256 deadline)" ); // Hash of the EIP712 Domain Separator data // solhint-disable-next-line var-name-mixedcase bytes32 public EIP712_DOMAIN_HASH; /** * EVENTS */ // ERC20 BASIC EVENTS event Transfer(address indexed from, address indexed to, uint256 value); // ERC20 EVENTS event Approval( address indexed owner, address indexed spender, uint256 value ); // OWNABLE EVENTS event OwnershipTransferProposed( address indexed currentOwner, address indexed proposedOwner ); event OwnershipTransferDisregarded( address indexed oldProposedOwner ); event OwnershipTransferred( address indexed oldOwner, address indexed newOwner ); // PAUSABLE EVENTS event Pause(); event Unpause(); // ASSET PROTECTION EVENTS event AddressFrozen(address indexed addr); event AddressUnfrozen(address indexed addr); event FrozenAddressWiped(address indexed addr); event AssetProtectionRoleSet ( address indexed oldAssetProtectionRole, address indexed newAssetProtectionRole ); // SUPPLY CONTROL EVENTS event SupplyIncreased(address indexed to, uint256 value); event SupplyDecreased(address indexed from, uint256 value); event SupplyControllerSet( address indexed oldSupplyController, address indexed newSupplyController ); // DELEGATED TRANSFER EVENTS event BetaDelegatedTransfer( address indexed from, address indexed to, uint256 value, uint256 seq, uint256 fee ); event BetaDelegateWhitelisterSet( address indexed oldWhitelister, address indexed newWhitelister ); event BetaDelegateWhitelisted(address indexed newDelegate); event BetaDelegateUnwhitelisted(address indexed oldDelegate); /** * FUNCTIONALITY */ // INITIALIZATION FUNCTIONALITY /** * @dev sets 0 initials tokens, the owner, and the supplyController. * this serves as the constructor for the proxy but compiles to the * memory model of the Implementation contract. */ function initialize() public { require(!initialized, "MANDATORY VERIFICATION REQUIRED: The proxy has already been initialized, verify the owner and supply controller addresses."); owner = msg.sender; assetProtectionRole = address(0); totalSupply_ = 0; supplyController = msg.sender; initializeDomainSeparator(); initialized = true; } /** * The constructor is used here to ensure that the implementation * contract is initialized. An uncontrolled implementation * contract might lead to misleading state * for users who accidentally interact with it. */ constructor() public { initialize(); pause(); } /** * @dev To be called when upgrading the contract using upgradeAndCall to add delegated transfers */ function initializeDomainSeparator() private { // hash the name context with the contract address EIP712_DOMAIN_HASH = keccak256(abi.encodePacked(// solium-disable-line EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH, keccak256(bytes(name)), bytes32(address(this)) )); } // ERC20 BASIC FUNCTIONALITY /** * @dev Total number of tokens in existence */ function totalSupply() public view returns (uint256) { return totalSupply_; } /** * @dev Transfer token to a specified address from msg.sender * Note: the use of Safemath ensures that _value is nonnegative. * @param _to The address to transfer to. * @param _value The amount to be transferred. */ function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) { require(_to != address(0), "cannot transfer to address zero"); require(!frozen[_to] && !frozen[msg.sender], "address frozen"); require(_value <= balances[msg.sender], "insufficient funds"); balances[msg.sender] = balances[msg.sender].sub(_value); balances[_to] = balances[_to].add(_value); emit Transfer(msg.sender, _to, _value); return true; } /** * @dev Gets the balance of the specified address. * @param _addr The address to query the the balance of. * @return An uint256 representing the amount owned by the passed address. */ function balanceOf(address _addr) public view returns (uint256) { return balances[_addr]; } // ERC20 FUNCTIONALITY /** * @dev Transfer tokens from one address to another * @param _from address The address which you want to send tokens from * @param _to address The address which you want to transfer to * @param _value uint256 the amount of tokens to be transferred */ function transferFrom( address _from, address _to, uint256 _value ) public whenNotPaused returns (bool) { require(_to != address(0), "cannot transfer to address zero"); require(!frozen[_to] && !frozen[_from] && !frozen[msg.sender], "address frozen"); require(_value <= balances[_from], "insufficient funds"); require(_value <= allowed[_from][msg.sender], "insufficient allowance"); balances[_from] = balances[_from].sub(_value); balances[_to] = balances[_to].add(_value); allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); emit Transfer(_from, _to, _value); return true; } /** * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. * Beware that changing an allowance with this method brings the risk that someone may use both the old * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * @param _spender The address which will spend the funds. * @param _value The amount of tokens to be spent. */ function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) { require(!frozen[_spender] && !frozen[msg.sender], "address frozen"); allowed[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); return true; } /** * @dev Increase the amount of tokens that an owner allowed to a spender. * * To increment allowed value is better to use this function to avoid 2 calls (and wait until the first transaction * is mined) instead of approve. * @param _spender The address which will spend the funds. * @param _addedValue The amount of tokens to increase the allowance by. */ function increaseApproval(address _spender, uint _addedValue) public whenNotPaused returns (bool) { require(!frozen[_spender] && !frozen[msg.sender], "address frozen"); allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue); emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } /** * @dev Decrease the amount of tokens that an owner allowed to a spender. * * To decrement allowed value is better to use this function to avoid 2 calls (and wait until the first transaction * is mined) instead of approve. * @param _spender The address which will spend the funds. * @param _subtractedValue The amount of tokens to decrease the allowance by. */ function decreaseApproval(address _spender, uint _subtractedValue) public whenNotPaused returns (bool) { require(!frozen[_spender] && !frozen[msg.sender], "address frozen"); uint oldValue = allowed[msg.sender][_spender]; if (_subtractedValue > oldValue) { allowed[msg.sender][_spender] = 0; } else { allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); } emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } /** * @dev Function to check the amount of tokens that an owner allowed to a spender. * @param _owner address The address which owns the funds. * @param _spender address The address which will spend the funds. * @return A uint256 specifying the amount of tokens still available for the spender. */ function allowance( address _owner, address _spender ) public view returns (uint256) { return allowed[_owner][_spender]; } // OWNER FUNCTIONALITY /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(msg.sender == owner, "onlyOwner"); _; } /** * @dev Allows the current owner to begin transferring control of the contract to a proposedOwner * @param _proposedOwner The address to transfer ownership to. */ function proposeOwner(address _proposedOwner) public onlyOwner { require(_proposedOwner != address(0), "cannot transfer ownership to address zero"); require(msg.sender != _proposedOwner, "caller already is owner"); proposedOwner = _proposedOwner; emit OwnershipTransferProposed(owner, proposedOwner); } /** * @dev Allows the current owner or proposed owner to cancel transferring control of the contract to a proposedOwner */ function disregardProposeOwner() public { require(msg.sender == proposedOwner || msg.sender == owner, "only proposedOwner or owner"); require(proposedOwner != address(0), "can only disregard a proposed owner that was previously set"); address _oldProposedOwner = proposedOwner; proposedOwner = address(0); emit OwnershipTransferDisregarded(_oldProposedOwner); } /** * @dev Allows the proposed owner to complete transferring control of the contract to the proposedOwner. */ function claimOwnership() public { require(msg.sender == proposedOwner, "onlyProposedOwner"); address _oldOwner = owner; owner = proposedOwner; proposedOwner = address(0); emit OwnershipTransferred(_oldOwner, owner); } /** * @dev Reclaim all PYUSD at the contract address. * This sends the PYUSD tokens that this contract add holding to the owner. * Note: this is not affected by freeze constraints. */ function reclaimPYUSD() external onlyOwner { uint256 _balance = balances[this]; balances[this] = 0; balances[owner] = balances[owner].add(_balance); emit Transfer(this, owner, _balance); } // PAUSABILITY FUNCTIONALITY /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!paused, "whenNotPaused"); _; } /** * @dev called by the owner to pause, triggers stopped state */ function pause() public onlyOwner { require(!paused, "already paused"); paused = true; emit Pause(); } /** * @dev called by the owner to unpause, returns to normal state */ function unpause() public onlyOwner { require(paused, "already unpaused"); paused = false; emit Unpause(); } // ASSET PROTECTION FUNCTIONALITY /** * @dev Sets a new asset protection role address. * @param _newAssetProtectionRole The new address allowed to freeze/unfreeze addresses and seize their tokens. */ function setAssetProtectionRole(address _newAssetProtectionRole) public { require(msg.sender == assetProtectionRole || msg.sender == owner, "only assetProtectionRole or Owner"); require(assetProtectionRole != _newAssetProtectionRole, "new address is same as a current one"); emit AssetProtectionRoleSet(assetProtectionRole, _newAssetProtectionRole); assetProtectionRole = _newAssetProtectionRole; } modifier onlyAssetProtectionRole() { require(msg.sender == assetProtectionRole, "onlyAssetProtectionRole"); _; } /** * @dev Freezes an address balance from being transferred. * @param _addr The new address to freeze. */ function freeze(address _addr) public onlyAssetProtectionRole { require(!frozen[_addr], "address already frozen"); frozen[_addr] = true; emit AddressFrozen(_addr); } /** * @dev Unfreezes an address balance allowing transfer. * @param _addr The new address to unfreeze. */ function unfreeze(address _addr) public onlyAssetProtectionRole { require(frozen[_addr], "address already unfrozen"); frozen[_addr] = false; emit AddressUnfrozen(_addr); } /** * @dev Wipes the balance of a frozen address, and burns the tokens. * @param _addr The new frozen address to wipe. */ function wipeFrozenAddress(address _addr) public onlyAssetProtectionRole { require(frozen[_addr], "address is not frozen"); uint256 _balance = balances[_addr]; balances[_addr] = 0; totalSupply_ = totalSupply_.sub(_balance); emit FrozenAddressWiped(_addr); emit SupplyDecreased(_addr, _balance); emit Transfer(_addr, address(0), _balance); } /** * @dev Gets whether the address is currently frozen. * @param _addr The address to check if frozen. * @return A bool representing whether the given address is frozen. */ function isFrozen(address _addr) public view returns (bool) { return frozen[_addr]; } // SUPPLY CONTROL FUNCTIONALITY /** * @dev Sets a new supply controller address. * @param _newSupplyController The address allowed to burn/mint tokens to control supply. */ function setSupplyController(address _newSupplyController) public { require(msg.sender == supplyController || msg.sender == owner, "only SupplyController or Owner"); require(_newSupplyController != address(0), "cannot set supply controller to address zero"); require(supplyController != _newSupplyController, "new address is same as a current one"); emit SupplyControllerSet(supplyController, _newSupplyController); supplyController = _newSupplyController; } modifier onlySupplyController() { require(msg.sender == supplyController, "onlySupplyController"); _; } /** * @dev Increases the total supply by minting the specified number of tokens to the supply controller account. * @param _value The number of tokens to add. * @return A boolean that indicates if the operation was successful. */ function increaseSupply(uint256 _value) public onlySupplyController returns (bool success) { totalSupply_ = totalSupply_.add(_value); balances[supplyController] = balances[supplyController].add(_value); emit SupplyIncreased(supplyController, _value); emit Transfer(address(0), supplyController, _value); return true; } /** * @dev Decreases the total supply by burning the specified number of tokens from the supply controller account. * @param _value The number of tokens to remove. * @return A boolean that indicates if the operation was successful. */ function decreaseSupply(uint256 _value) public onlySupplyController returns (bool success) { require(_value <= balances[supplyController], "not enough supply"); balances[supplyController] = balances[supplyController].sub(_value); totalSupply_ = totalSupply_.sub(_value); emit SupplyDecreased(supplyController, _value); emit Transfer(supplyController, address(0), _value); return true; } // DELEGATED TRANSFER FUNCTIONALITY /** * @dev returns the next seq for a target address. * The transactor must submit nextSeqOf(transactor) in the next transaction for it to be valid. * Note: that the seq context is specific to this smart contract. * @param target The target address. * @return the seq. */ // function nextSeqOf(address target) public view returns (uint256) { return nextSeqs[target]; } /** * @dev Performs a transfer on behalf of the from address, identified by its signature on the delegatedTransfer msg. * Splits a signature byte array into r,s,v for convenience. * @param sig the signature of the delgatedTransfer msg. * @param to The address to transfer to. * @param value The amount to be transferred. * @param fee an optional ERC20 fee paid to the executor of betaDelegatedTransfer by the from address. * @param seq a sequencing number included by the from address specific to this contract to protect from replays. * @param deadline a block number after which the pre-signed transaction has expired. * @return A boolean that indicates if the operation was successful. */ function betaDelegatedTransfer( bytes sig, address to, uint256 value, uint256 fee, uint256 seq, uint256 deadline ) public returns (bool) { require(sig.length == 65, "signature should have length 65"); bytes32 r; bytes32 s; uint8 v; assembly { r := mload(add(sig, 32)) s := mload(add(sig, 64)) v := byte(0, mload(add(sig, 96))) } _betaDelegatedTransfer(r, s, v, to, value, fee, seq, deadline); return true; } /** * @dev Performs a transfer on behalf of the from address, identified by its signature on the betaDelegatedTransfer msg. * Note: both the delegate and transactor sign in the fees. The transactor, however, * has no control over the gas price, and therefore no control over the transaction time. * Beta prefix chosen to avoid a name clash with an emerging standard in ERC865 or elsewhere. * Internal to the contract - see betaDelegatedTransfer and betaDelegatedTransferBatch. * @param r the r signature of the delgatedTransfer msg. * @param s the s signature of the delgatedTransfer msg. * @param v the v signature of the delgatedTransfer msg. * @param to The address to transfer to. * @param value The amount to be transferred. * @param fee an optional ERC20 fee paid to the delegate of betaDelegatedTransfer by the from address. * @param seq a sequencing number included by the from address specific to this contract to protect from replays. * @param deadline a block number after which the pre-signed transaction has expired. * @return A boolean that indicates if the operation was successful. */ function _betaDelegatedTransfer( bytes32 r, bytes32 s, uint8 v, address to, uint256 value, uint256 fee, uint256 seq, uint256 deadline ) internal whenNotPaused returns (bool) { require(betaDelegateWhitelist[msg.sender], "Beta feature only accepts whitelisted delegates"); require(value > 0 || fee > 0, "cannot transfer zero tokens with zero fee"); require(block.number <= deadline, "transaction expired"); // prevent sig malleability from ecrecover() require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "signature incorrect"); require(v == 27 || v == 28, "signature incorrect"); // EIP712 scheme: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md bytes32 delegatedTransferHash = keccak256(abi.encodePacked(// solium-disable-line EIP712_DELEGATED_TRANSFER_SCHEMA_HASH, bytes32(to), value, fee, seq, deadline )); bytes32 hash = keccak256(abi.encodePacked(EIP191_HEADER, EIP712_DOMAIN_HASH, delegatedTransferHash)); address _from = ecrecover(hash, v, r, s); require(_from != address(0), "error determining from address from signature"); require(to != address(0), "canno use address zero"); require(!frozen[to] && !frozen[_from] && !frozen[msg.sender], "address frozen"); require(value.add(fee) <= balances[_from], "insufficient fund"); require(nextSeqs[_from] == seq, "incorrect seq"); nextSeqs[_from] = nextSeqs[_from].add(1); balances[_from] = balances[_from].sub(value.add(fee)); if (fee != 0) { balances[msg.sender] = balances[msg.sender].add(fee); emit Transfer(_from, msg.sender, fee); } balances[to] = balances[to].add(value); emit Transfer(_from, to, value); emit BetaDelegatedTransfer(_from, to, value, seq, fee); return true; } /** * @dev Performs an atomic batch of transfers on behalf of the from addresses, identified by their signatures. * Lack of nested array support in arguments requires all arguments to be passed as equal size arrays where * delegated transfer number i is the combination of all arguments at index i * @param r the r signatures of the delgatedTransfer msg. * @param s the s signatures of the delgatedTransfer msg. * @param v the v signatures of the delgatedTransfer msg. * @param to The addresses to transfer to. * @param value The amounts to be transferred. * @param fee optional ERC20 fees paid to the delegate of betaDelegatedTransfer by the from address. * @param seq sequencing numbers included by the from address specific to this contract to protect from replays. * @param deadline block numbers after which the pre-signed transactions have expired. * @return A boolean that indicates if the operation was successful. */ function betaDelegatedTransferBatch( bytes32[] r, bytes32[] s, uint8[] v, address[] to, uint256[] value, uint256[] fee, uint256[] seq, uint256[] deadline ) public returns (bool) { require(r.length == s.length && r.length == v.length && r.length == to.length && r.length == value.length, "length mismatch"); require(r.length == fee.length && r.length == seq.length && r.length == deadline.length, "length mismatch"); for (uint i = 0; i < r.length; i++) { _betaDelegatedTransfer(r[i], s[i], v[i], to[i], value[i], fee[i], seq[i], deadline[i]); } return true; } /** * @dev Gets whether the address is currently whitelisted for betaDelegateTransfer. * @param _addr The address to check if whitelisted. * @return A bool representing whether the given address is whitelisted. */ function isWhitelistedBetaDelegate(address _addr) public view returns (bool) { return betaDelegateWhitelist[_addr]; } /** * @dev Sets a new betaDelegate whitelister. * @param _newWhitelister The address allowed to whitelist betaDelegates. */ function setBetaDelegateWhitelister(address _newWhitelister) public { require(msg.sender == betaDelegateWhitelister || msg.sender == owner, "only Whitelister or Owner"); require(betaDelegateWhitelister != _newWhitelister, "new address is same as a current one"); betaDelegateWhitelister = _newWhitelister; emit BetaDelegateWhitelisterSet(betaDelegateWhitelister, _newWhitelister); } modifier onlyBetaDelegateWhitelister() { require(msg.sender == betaDelegateWhitelister, "onlyBetaDelegateWhitelister"); _; } /** * @dev Whitelists an address to allow calling BetaDelegatedTransfer. * @param _addr The new address to whitelist. */ function whitelistBetaDelegate(address _addr) public onlyBetaDelegateWhitelister { require(!betaDelegateWhitelist[_addr], "delegate already whitelisted"); betaDelegateWhitelist[_addr] = true; emit BetaDelegateWhitelisted(_addr); } /** * @dev Unwhitelists an address to disallow calling BetaDelegatedTransfer. * @param _addr The new address to whitelist. */ function unwhitelistBetaDelegate(address _addr) public onlyBetaDelegateWhitelister { require(betaDelegateWhitelist[_addr], "delegate not whitelisted"); betaDelegateWhitelist[_addr] = false; emit BetaDelegateUnwhitelisted(_addr); } }
違いを見つける