add amb base implementation on oracle
This commit is contained in:
parent
94e923d965
commit
7ca3b0079c
682
oracle/abis/ForeignAMB.abi.json
Normal file
682
oracle/abis/ForeignAMB.abi.json
Normal file
@ -0,0 +1,682 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_contract",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_data",
|
||||||
|
"type": "bytes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_gas",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_oracleGasPriceSpeed",
|
||||||
|
"type": "bytes1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "requireToPassMessage",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_contract",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "depositForContractSender",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": true,
|
||||||
|
"stateMutability": "payable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_txHash",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "relayedMessages",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_day",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "totalSpentPerDay",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "isInitialized",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "setDefrayalModeForHomeToForeign",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getCurrentDay",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "requiredBlockConfirmations",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_data",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "getMinimumGasUsage",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "gas",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getBridgeMode",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "_data",
|
||||||
|
"type": "bytes4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "setSubsidizedModeForForeignToHome",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_validatorContract",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_maxGasPerTx",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_gasPrice",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_requiredBlockConfirmations",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "initialize",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_data",
|
||||||
|
"type": "bytes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "vs",
|
||||||
|
"type": "uint8[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "rs",
|
||||||
|
"type": "bytes32[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ss",
|
||||||
|
"type": "bytes32[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "executeSignatures",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "dailyLimit",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_token",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_to",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "claimTokens",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "homeToForeignMode",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_balanceHolder",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "balanceOf",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_maxGasPerTx",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setMaxGasPerTx",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_recipient",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "withdrawFromDeposit",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "setSubsidizedModeForHomeToForeign",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "requiredSignatures",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "foreignToHomeMode",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "setDefrayalModeForForeignToHome",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "validatorContract",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "deployedAtBlock",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getBridgeInterfacesVersion",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "major",
|
||||||
|
"type": "uint64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "minor",
|
||||||
|
"type": "uint64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "patch",
|
||||||
|
"type": "uint64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_minPerTx",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setMinPerTx",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_blockConfirmations",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setRequiredBlockConfirmations",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_dailyLimit",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setDailyLimit",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_gasPrice",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setGasPrice",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_maxPerTx",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setMaxPerTx",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_contract",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_data",
|
||||||
|
"type": "bytes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_gas",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "requireToPassMessage",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "minPerTx",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "maxGasPerTx",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_contract",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_data",
|
||||||
|
"type": "bytes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_gas",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_gasPrice",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "requireToPassMessage",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_amount",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "withinLimit",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "maxPerTx",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "gasPrice",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "encodedData",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "UserRequestForAffirmation",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "sender",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "executor",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "transactionHash",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "RelayedMessage",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "gasPrice",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "GasPriceChanged",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "requiredBlockConfirmations",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "RequiredBlockConfirmationChanged",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "newLimit",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "DailyLimitChanged",
|
||||||
|
"type": "event"
|
||||||
|
}
|
||||||
|
]
|
862
oracle/abis/HomeAMB.abi.json
Normal file
862
oracle/abis/HomeAMB.abi.json
Normal file
@ -0,0 +1,862 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_message",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "numMessagesSigned",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_contract",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_data",
|
||||||
|
"type": "bytes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_gas",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_oracleGasPriceSpeed",
|
||||||
|
"type": "bytes1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "requireToPassMessage",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_contract",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "depositForContractSender",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": true,
|
||||||
|
"stateMutability": "payable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_hash",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_index",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "signature",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_day",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "totalSpentPerDay",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "isInitialized",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "setDefrayalModeForHomeToForeign",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getCurrentDay",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "requiredBlockConfirmations",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_data",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "getMinimumGasUsage",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "gas",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getBridgeMode",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "_data",
|
||||||
|
"type": "bytes4"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_hash",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "message",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "setSubsidizedModeForForeignToHome",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_validatorContract",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_maxGasPerTx",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_gasPrice",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_requiredBlockConfirmations",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "initialize",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "signature",
|
||||||
|
"type": "bytes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "message",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "submitSignature",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "dailyLimit",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_token",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_to",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "claimTokens",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_hash",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "numAffirmationsSigned",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "homeToForeignMode",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_balanceHolder",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "balanceOf",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_hash",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "affirmationsSigned",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_maxGasPerTx",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setMaxGasPerTx",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_recipient",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "withdrawFromDeposit",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "setSubsidizedModeForHomeToForeign",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "requiredSignatures",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_message",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "messagesSigned",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "foreignToHomeMode",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "setDefrayalModeForForeignToHome",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "validatorContract",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "address"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "deployedAtBlock",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getBridgeInterfacesVersion",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "major",
|
||||||
|
"type": "uint64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "minor",
|
||||||
|
"type": "uint64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "patch",
|
||||||
|
"type": "uint64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_minPerTx",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setMinPerTx",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_blockConfirmations",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setRequiredBlockConfirmations",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_dailyLimit",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setDailyLimit",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_gasPrice",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setGasPrice",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_maxPerTx",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "setMaxPerTx",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_contract",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_data",
|
||||||
|
"type": "bytes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_gas",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "requireToPassMessage",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "minPerTx",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "maxGasPerTx",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "message",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "executeAffirmation",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_contract",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_data",
|
||||||
|
"type": "bytes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_gas",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "_gasPrice",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "requireToPassMessage",
|
||||||
|
"outputs": [],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_amount",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "withinLimit",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "maxPerTx",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [],
|
||||||
|
"name": "gasPrice",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"constant": true,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"name": "_number",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "isAlreadyProcessed",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"payable": false,
|
||||||
|
"stateMutability": "pure",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "encodedData",
|
||||||
|
"type": "bytes"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "UserRequestForSignature",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "sender",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "executor",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "txHash",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "AffirmationCompleted",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"name": "signer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "messageHash",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "SignedForUserRequest",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": true,
|
||||||
|
"name": "signer",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "messageHash",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "SignedForAffirmation",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "authorityResponsibleForRelay",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "messageHash",
|
||||||
|
"type": "bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "NumberOfCollectedSignatures",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "CollectedSignatures",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "gasPrice",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "GasPriceChanged",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "requiredBlockConfirmations",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "RequiredBlockConfirmationChanged",
|
||||||
|
"type": "event"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"anonymous": false,
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"indexed": false,
|
||||||
|
"name": "newLimit",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "DailyLimitChanged",
|
||||||
|
"type": "event"
|
||||||
|
}
|
||||||
|
]
|
@ -13,6 +13,9 @@ const foreignErc677Erc677Abi = require('../abis/ForeignBridgeErc677ToErc677.abi'
|
|||||||
const homeErcNativeAbi = require('../abis/HomeBridgeErcToNative.abi')
|
const homeErcNativeAbi = require('../abis/HomeBridgeErcToNative.abi')
|
||||||
const foreignErcNativeAbi = require('../abis/ForeignBridgeErcToNative.abi')
|
const foreignErcNativeAbi = require('../abis/ForeignBridgeErcToNative.abi')
|
||||||
|
|
||||||
|
const homeAMBAbi = require('../abis/HomeAMB.abi')
|
||||||
|
const foreignAMBAbi = require('../abis/ForeignAMB.abi')
|
||||||
|
|
||||||
const { VALIDATOR_ADDRESS, VALIDATOR_ADDRESS_PRIVATE_KEY } = process.env
|
const { VALIDATOR_ADDRESS, VALIDATOR_ADDRESS_PRIVATE_KEY } = process.env
|
||||||
|
|
||||||
let homeAbi
|
let homeAbi
|
||||||
@ -35,6 +38,11 @@ switch (process.env.BRIDGE_MODE) {
|
|||||||
foreignAbi = foreignErcNativeAbi
|
foreignAbi = foreignErcNativeAbi
|
||||||
id = 'erc-native'
|
id = 'erc-native'
|
||||||
break
|
break
|
||||||
|
case 'ARBITRARY_MESSAGE':
|
||||||
|
homeAbi = homeAMBAbi
|
||||||
|
foreignAbi = foreignAMBAbi
|
||||||
|
id = 'amb'
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
if (process.env.NODE_ENV !== 'test') {
|
if (process.env.NODE_ENV !== 'test') {
|
||||||
throw new Error(`Bridge Mode: ${process.env.BRIDGE_MODE} not supported.`)
|
throw new Error(`Bridge Mode: ${process.env.BRIDGE_MODE} not supported.`)
|
||||||
|
@ -0,0 +1,57 @@
|
|||||||
|
const { HttpListProviderError } = require('http-list-provider')
|
||||||
|
const {
|
||||||
|
AlreadyProcessedError,
|
||||||
|
AlreadySignedError,
|
||||||
|
InvalidValidatorError
|
||||||
|
} = require('../../utils/errors')
|
||||||
|
const logger = require('../../services/logger').child({
|
||||||
|
module: 'processAffirmationRequests:estimateGas'
|
||||||
|
})
|
||||||
|
|
||||||
|
async function estimateGas({ web3, homeBridge, validatorContract, message, address }) {
|
||||||
|
try {
|
||||||
|
const gasEstimate = await homeBridge.methods.executeAffirmation(message).estimateGas({
|
||||||
|
from: address
|
||||||
|
})
|
||||||
|
|
||||||
|
return gasEstimate
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof HttpListProviderError) {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
|
||||||
|
const messageHash = web3.utils.soliditySha3(message)
|
||||||
|
const senderHash = web3.utils.soliditySha3(address, messageHash)
|
||||||
|
|
||||||
|
// Check if minimum number of validations was already reached
|
||||||
|
logger.debug('Check if minimum number of validations was already reached')
|
||||||
|
const numAffirmationsSigned = await homeBridge.methods.numAffirmationsSigned(messageHash).call()
|
||||||
|
const alreadyProcessed = await homeBridge.methods
|
||||||
|
.isAlreadyProcessed(numAffirmationsSigned)
|
||||||
|
.call()
|
||||||
|
|
||||||
|
if (alreadyProcessed) {
|
||||||
|
throw new AlreadyProcessedError(e.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the message was already signed by this validator
|
||||||
|
logger.debug('Check if the message was already signed')
|
||||||
|
const alreadySigned = await homeBridge.methods.affirmationsSigned(senderHash).call()
|
||||||
|
|
||||||
|
if (alreadySigned) {
|
||||||
|
throw new AlreadySignedError(e.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if address is validator
|
||||||
|
logger.debug('Check if address is a validator')
|
||||||
|
const isValidator = await validatorContract.methods.isValidator(address).call()
|
||||||
|
|
||||||
|
if (!isValidator) {
|
||||||
|
throw new InvalidValidatorError(`${address} is not a validator`)
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('Unknown error while processing message')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = estimateGas
|
110
oracle/src/events/processAMBAffirmationRequests/index.js
Normal file
110
oracle/src/events/processAMBAffirmationRequests/index.js
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
require('dotenv').config()
|
||||||
|
const { HttpListProviderError } = require('http-list-provider')
|
||||||
|
const promiseLimit = require('promise-limit')
|
||||||
|
const rootLogger = require('../../services/logger')
|
||||||
|
const { web3Home } = require('../../services/web3')
|
||||||
|
const bridgeValidatorsABI = require('../../../abis/BridgeValidators.abi')
|
||||||
|
const { EXIT_CODES, MAX_CONCURRENT_EVENTS } = require('../../utils/constants')
|
||||||
|
const estimateGas = require('./estimateGas')
|
||||||
|
const { addTxHashToData, parseAMBMessage } = require('../../utils/message')
|
||||||
|
const { generateGasPriceOptions } = require('../../utils/utils')
|
||||||
|
const {
|
||||||
|
AlreadyProcessedError,
|
||||||
|
AlreadySignedError,
|
||||||
|
InvalidValidatorError
|
||||||
|
} = require('../../utils/errors')
|
||||||
|
|
||||||
|
const limit = promiseLimit(MAX_CONCURRENT_EVENTS)
|
||||||
|
|
||||||
|
let validatorContract = null
|
||||||
|
|
||||||
|
function processAffirmationRequestsBuilder(config) {
|
||||||
|
const homeBridge = new web3Home.eth.Contract(config.homeBridgeAbi, config.homeBridgeAddress)
|
||||||
|
|
||||||
|
return async function processAffirmationRequests(affirmationRequests) {
|
||||||
|
const txToSend = []
|
||||||
|
|
||||||
|
if (validatorContract === null) {
|
||||||
|
rootLogger.debug('Getting validator contract address')
|
||||||
|
const validatorContractAddress = await homeBridge.methods.validatorContract().call()
|
||||||
|
rootLogger.debug({ validatorContractAddress }, 'Validator contract address obtained')
|
||||||
|
|
||||||
|
validatorContract = new web3Home.eth.Contract(bridgeValidatorsABI, validatorContractAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
rootLogger.debug(`Processing ${affirmationRequests.length} AffirmationRequest events`)
|
||||||
|
const callbacks = affirmationRequests.map(affirmationRequest =>
|
||||||
|
limit(async () => {
|
||||||
|
const { encodedData } = affirmationRequest.returnValues
|
||||||
|
|
||||||
|
const logger = rootLogger.child({
|
||||||
|
eventTransactionHash: affirmationRequest.transactionHash
|
||||||
|
})
|
||||||
|
|
||||||
|
const message = addTxHashToData({
|
||||||
|
encodedData,
|
||||||
|
transactionHash: affirmationRequest.transactionHash
|
||||||
|
})
|
||||||
|
|
||||||
|
const { sender, executor, dataType, gasPrice, gasPriceSpeed } = parseAMBMessage(message)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
{ sender, executor },
|
||||||
|
`Processing affirmationRequest ${affirmationRequest.transactionHash}`
|
||||||
|
)
|
||||||
|
|
||||||
|
let gasEstimate
|
||||||
|
try {
|
||||||
|
logger.debug('Estimate gas')
|
||||||
|
gasEstimate = await estimateGas({
|
||||||
|
web3: web3Home,
|
||||||
|
homeBridge,
|
||||||
|
validatorContract,
|
||||||
|
message,
|
||||||
|
address: config.validatorAddress
|
||||||
|
})
|
||||||
|
logger.debug({ gasEstimate }, 'Gas estimated')
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof HttpListProviderError) {
|
||||||
|
throw new Error(
|
||||||
|
'RPC Connection Error: submitSignature Gas Estimate cannot be obtained.'
|
||||||
|
)
|
||||||
|
} else if (e instanceof InvalidValidatorError) {
|
||||||
|
logger.fatal({ address: config.validatorAddress }, 'Invalid validator')
|
||||||
|
process.exit(EXIT_CODES.INCOMPATIBILITY)
|
||||||
|
} else if (e instanceof AlreadySignedError) {
|
||||||
|
logger.info(`Already signed affirmationRequest ${affirmationRequest.transactionHash}`)
|
||||||
|
return
|
||||||
|
} else if (e instanceof AlreadyProcessedError) {
|
||||||
|
logger.info(
|
||||||
|
`affirmationRequest ${
|
||||||
|
affirmationRequest.transactionHash
|
||||||
|
} was already processed by other validators`
|
||||||
|
)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
logger.error(e, 'Unknown error while processing transaction')
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await homeBridge.methods.executeAffirmation(message).encodeABI()
|
||||||
|
|
||||||
|
const gasPriceOptions = generateGasPriceOptions({ dataType, gasPrice, gasPriceSpeed })
|
||||||
|
|
||||||
|
txToSend.push({
|
||||||
|
data,
|
||||||
|
gasEstimate,
|
||||||
|
transactionReference: affirmationRequest.transactionHash,
|
||||||
|
to: config.homeBridgeAddress,
|
||||||
|
gasPriceOptions
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(callbacks)
|
||||||
|
return txToSend
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = processAffirmationRequestsBuilder
|
@ -0,0 +1,67 @@
|
|||||||
|
const Web3 = require('web3')
|
||||||
|
const { HttpListProviderError } = require('http-list-provider')
|
||||||
|
const {
|
||||||
|
AlreadyProcessedError,
|
||||||
|
IncompatibleContractError,
|
||||||
|
InvalidValidatorError
|
||||||
|
} = require('../../utils/errors')
|
||||||
|
const logger = require('../../services/logger').child({
|
||||||
|
module: 'processCollectedSignatures:estimateGas'
|
||||||
|
})
|
||||||
|
|
||||||
|
const web3 = new Web3()
|
||||||
|
const { toBN } = Web3.utils
|
||||||
|
|
||||||
|
async function estimateGas({
|
||||||
|
foreignBridge,
|
||||||
|
validatorContract,
|
||||||
|
message,
|
||||||
|
numberOfCollectedSignatures,
|
||||||
|
v,
|
||||||
|
r,
|
||||||
|
s,
|
||||||
|
txHash,
|
||||||
|
address
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
const gasEstimate = await foreignBridge.methods
|
||||||
|
.executeSignatures(message, v, r, s)
|
||||||
|
.estimateGas({
|
||||||
|
from: address
|
||||||
|
})
|
||||||
|
return gasEstimate
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof HttpListProviderError) {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the message was already processed
|
||||||
|
logger.debug('Check if the message was already processed')
|
||||||
|
const alreadyProcessed = await foreignBridge.methods.relayedMessages(txHash).call()
|
||||||
|
if (alreadyProcessed) {
|
||||||
|
throw new AlreadyProcessedError()
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the number of signatures is enough
|
||||||
|
logger.debug('Check if number of signatures is enough')
|
||||||
|
const requiredSignatures = await validatorContract.methods.requiredSignatures().call()
|
||||||
|
if (toBN(requiredSignatures).gt(toBN(numberOfCollectedSignatures))) {
|
||||||
|
throw new IncompatibleContractError('The number of collected signatures does not match')
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if all the signatures were made by validators
|
||||||
|
for (let i = 0; i < v.length; i++) {
|
||||||
|
const address = web3.eth.accounts.recover(message, web3.utils.toHex(v[i]), r[i], s[i])
|
||||||
|
logger.debug({ address }, 'Check that signature is from a validator')
|
||||||
|
const isValidator = await validatorContract.methods.isValidator(address).call()
|
||||||
|
|
||||||
|
if (!isValidator) {
|
||||||
|
throw new InvalidValidatorError(`Message signed by ${address} that is not a validator`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error('Unknown error while processing message')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = estimateGas
|
140
oracle/src/events/processAMBCollectedSignatures/index.js
Normal file
140
oracle/src/events/processAMBCollectedSignatures/index.js
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
require('dotenv').config()
|
||||||
|
const promiseLimit = require('promise-limit')
|
||||||
|
const { HttpListProviderError } = require('http-list-provider')
|
||||||
|
const bridgeValidatorsABI = require('../../../abis/BridgeValidators.abi')
|
||||||
|
const rootLogger = require('../../services/logger')
|
||||||
|
const { web3Home, web3Foreign } = require('../../services/web3')
|
||||||
|
const { signatureToVRS, parseAMBMessage } = require('../../utils/message')
|
||||||
|
const { generateGasPriceOptions } = require('../../utils/utils')
|
||||||
|
const estimateGas = require('./estimateGas')
|
||||||
|
const {
|
||||||
|
AlreadyProcessedError,
|
||||||
|
IncompatibleContractError,
|
||||||
|
InvalidValidatorError
|
||||||
|
} = require('../../utils/errors')
|
||||||
|
const { MAX_CONCURRENT_EVENTS } = require('../../utils/constants')
|
||||||
|
|
||||||
|
const limit = promiseLimit(MAX_CONCURRENT_EVENTS)
|
||||||
|
|
||||||
|
let validatorContract = null
|
||||||
|
|
||||||
|
function processCollectedSignaturesBuilder(config) {
|
||||||
|
const homeBridge = new web3Home.eth.Contract(config.homeBridgeAbi, config.homeBridgeAddress)
|
||||||
|
|
||||||
|
const foreignBridge = new web3Foreign.eth.Contract(
|
||||||
|
config.foreignBridgeAbi,
|
||||||
|
config.foreignBridgeAddress
|
||||||
|
)
|
||||||
|
|
||||||
|
return async function processCollectedSignatures(signatures) {
|
||||||
|
const txToSend = []
|
||||||
|
|
||||||
|
if (validatorContract === null) {
|
||||||
|
rootLogger.debug('Getting validator contract address')
|
||||||
|
const validatorContractAddress = await foreignBridge.methods.validatorContract().call()
|
||||||
|
rootLogger.debug({ validatorContractAddress }, 'Validator contract address obtained')
|
||||||
|
|
||||||
|
validatorContract = new web3Foreign.eth.Contract(
|
||||||
|
bridgeValidatorsABI,
|
||||||
|
validatorContractAddress
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
rootLogger.debug(`Processing ${signatures.length} CollectedSignatures events`)
|
||||||
|
const callbacks = signatures.map(colSignature =>
|
||||||
|
limit(async () => {
|
||||||
|
const {
|
||||||
|
authorityResponsibleForRelay,
|
||||||
|
messageHash,
|
||||||
|
NumberOfCollectedSignatures
|
||||||
|
} = colSignature.returnValues
|
||||||
|
|
||||||
|
const logger = rootLogger.child({
|
||||||
|
eventTransactionHash: colSignature.transactionHash
|
||||||
|
})
|
||||||
|
|
||||||
|
if (
|
||||||
|
authorityResponsibleForRelay === web3Home.utils.toChecksumAddress(config.validatorAddress)
|
||||||
|
) {
|
||||||
|
logger.info(`Processing CollectedSignatures ${colSignature.transactionHash}`)
|
||||||
|
const message = await homeBridge.methods.message(messageHash).call()
|
||||||
|
|
||||||
|
const requiredSignatures = []
|
||||||
|
requiredSignatures.length = NumberOfCollectedSignatures
|
||||||
|
requiredSignatures.fill(0)
|
||||||
|
|
||||||
|
const [v, r, s] = [[], [], []]
|
||||||
|
logger.debug('Getting message signatures')
|
||||||
|
const signaturePromises = requiredSignatures.map(async (el, index) => {
|
||||||
|
logger.debug({ index }, 'Getting message signature')
|
||||||
|
const signature = await homeBridge.methods.signature(messageHash, index).call()
|
||||||
|
const recover = signatureToVRS(signature)
|
||||||
|
v.push(recover.v)
|
||||||
|
r.push(recover.r)
|
||||||
|
s.push(recover.s)
|
||||||
|
})
|
||||||
|
|
||||||
|
await Promise.all(signaturePromises)
|
||||||
|
|
||||||
|
const { dataType, gasPrice, gasPriceSpeed, txHash } = parseAMBMessage(message)
|
||||||
|
|
||||||
|
let gasEstimate
|
||||||
|
try {
|
||||||
|
logger.debug('Estimate gas')
|
||||||
|
gasEstimate = await estimateGas({
|
||||||
|
foreignBridge,
|
||||||
|
validatorContract,
|
||||||
|
v,
|
||||||
|
r,
|
||||||
|
s,
|
||||||
|
message,
|
||||||
|
numberOfCollectedSignatures: NumberOfCollectedSignatures,
|
||||||
|
txHash,
|
||||||
|
address: config.validatorAddress
|
||||||
|
})
|
||||||
|
logger.debug({ gasEstimate }, 'Gas estimated')
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof HttpListProviderError) {
|
||||||
|
throw new Error(
|
||||||
|
'RPC Connection Error: submitSignature Gas Estimate cannot be obtained.'
|
||||||
|
)
|
||||||
|
} else if (e instanceof AlreadyProcessedError) {
|
||||||
|
logger.info(`Already processed CollectedSignatures ${colSignature.transactionHash}`)
|
||||||
|
return
|
||||||
|
} else if (
|
||||||
|
e instanceof IncompatibleContractError ||
|
||||||
|
e instanceof InvalidValidatorError
|
||||||
|
) {
|
||||||
|
logger.error(`The message couldn't be processed; skipping: ${e.message}`)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
logger.error(e, 'Unknown error while processing transaction')
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const data = await foreignBridge.methods.executeSignatures(message, v, r, s).encodeABI()
|
||||||
|
const gasPriceOptions = generateGasPriceOptions({ dataType, gasPrice, gasPriceSpeed })
|
||||||
|
txToSend.push({
|
||||||
|
data,
|
||||||
|
gasEstimate,
|
||||||
|
transactionReference: colSignature.transactionHash,
|
||||||
|
to: config.foreignBridgeAddress,
|
||||||
|
gasPriceOptions
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
logger.info(
|
||||||
|
`Validator not responsible for relaying CollectedSignatures ${
|
||||||
|
colSignature.transactionHash
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(callbacks)
|
||||||
|
|
||||||
|
return txToSend
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = processCollectedSignaturesBuilder
|
112
oracle/src/events/processAMBSignatureRequests/index.js
Normal file
112
oracle/src/events/processAMBSignatureRequests/index.js
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
require('dotenv').config()
|
||||||
|
const promiseLimit = require('promise-limit')
|
||||||
|
const { HttpListProviderError } = require('http-list-provider')
|
||||||
|
const bridgeValidatorsABI = require('../../../abis/BridgeValidators.abi')
|
||||||
|
const rootLogger = require('../../services/logger')
|
||||||
|
const { web3Home } = require('../../services/web3')
|
||||||
|
const { addTxHashToData, parseAMBMessage } = require('../../utils/message')
|
||||||
|
const estimateGas = require('../processSignatureRequests/estimateGas')
|
||||||
|
const {
|
||||||
|
AlreadyProcessedError,
|
||||||
|
AlreadySignedError,
|
||||||
|
InvalidValidatorError
|
||||||
|
} = require('../../utils/errors')
|
||||||
|
const { EXIT_CODES, MAX_CONCURRENT_EVENTS } = require('../../utils/constants')
|
||||||
|
|
||||||
|
const { VALIDATOR_ADDRESS_PRIVATE_KEY } = process.env
|
||||||
|
|
||||||
|
const limit = promiseLimit(MAX_CONCURRENT_EVENTS)
|
||||||
|
|
||||||
|
let validatorContract = null
|
||||||
|
|
||||||
|
function processSignatureRequestsBuilder(config) {
|
||||||
|
const homeBridge = new web3Home.eth.Contract(config.homeBridgeAbi, config.homeBridgeAddress)
|
||||||
|
|
||||||
|
return async function processSignatureRequests(signatureRequests) {
|
||||||
|
const txToSend = []
|
||||||
|
|
||||||
|
if (validatorContract === null) {
|
||||||
|
rootLogger.debug('Getting validator contract address')
|
||||||
|
const validatorContractAddress = await homeBridge.methods.validatorContract().call()
|
||||||
|
rootLogger.debug({ validatorContractAddress }, 'Validator contract address obtained')
|
||||||
|
|
||||||
|
validatorContract = new web3Home.eth.Contract(bridgeValidatorsABI, validatorContractAddress)
|
||||||
|
}
|
||||||
|
|
||||||
|
rootLogger.debug(`Processing ${signatureRequests.length} SignatureRequest events`)
|
||||||
|
const callbacks = signatureRequests.map(signatureRequest =>
|
||||||
|
limit(async () => {
|
||||||
|
const { encodedData } = signatureRequest.returnValues
|
||||||
|
|
||||||
|
const logger = rootLogger.child({
|
||||||
|
eventTransactionHash: signatureRequest.transactionHash
|
||||||
|
})
|
||||||
|
|
||||||
|
const message = addTxHashToData({
|
||||||
|
encodedData,
|
||||||
|
transactionHash: signatureRequest.transactionHash
|
||||||
|
})
|
||||||
|
|
||||||
|
const { sender, executor } = parseAMBMessage(message)
|
||||||
|
logger.info(
|
||||||
|
{ sender, executor },
|
||||||
|
`Processing signatureRequest ${signatureRequest.transactionHash}`
|
||||||
|
)
|
||||||
|
|
||||||
|
const signature = web3Home.eth.accounts.sign(message, `0x${VALIDATOR_ADDRESS_PRIVATE_KEY}`)
|
||||||
|
|
||||||
|
let gasEstimate
|
||||||
|
try {
|
||||||
|
logger.debug('Estimate gas')
|
||||||
|
gasEstimate = await estimateGas({
|
||||||
|
web3: web3Home,
|
||||||
|
homeBridge,
|
||||||
|
validatorContract,
|
||||||
|
signature: signature.signature,
|
||||||
|
message,
|
||||||
|
address: config.validatorAddress
|
||||||
|
})
|
||||||
|
logger.debug({ gasEstimate }, 'Gas estimated')
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof HttpListProviderError) {
|
||||||
|
throw new Error(
|
||||||
|
'RPC Connection Error: submitSignature Gas Estimate cannot be obtained.'
|
||||||
|
)
|
||||||
|
} else if (e instanceof InvalidValidatorError) {
|
||||||
|
logger.fatal({ address: config.validatorAddress }, 'Invalid validator')
|
||||||
|
process.exit(EXIT_CODES.INCOMPATIBILITY)
|
||||||
|
} else if (e instanceof AlreadySignedError) {
|
||||||
|
logger.info(`Already signed signatureRequest ${signatureRequest.transactionHash}`)
|
||||||
|
return
|
||||||
|
} else if (e instanceof AlreadyProcessedError) {
|
||||||
|
logger.info(
|
||||||
|
`signatureRequest ${
|
||||||
|
signatureRequest.transactionHash
|
||||||
|
} was already processed by other validators`
|
||||||
|
)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
logger.error(e, 'Unknown error while processing transaction')
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await homeBridge.methods
|
||||||
|
.submitSignature(signature.signature, message)
|
||||||
|
.encodeABI({ from: config.validatorAddress })
|
||||||
|
|
||||||
|
txToSend.push({
|
||||||
|
data,
|
||||||
|
gasEstimate,
|
||||||
|
transactionReference: signatureRequest.transactionHash,
|
||||||
|
to: config.homeBridgeAddress
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
await Promise.all(callbacks)
|
||||||
|
return txToSend
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = processSignatureRequestsBuilder
|
@ -99,7 +99,6 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) {
|
|||||||
|
|
||||||
const txArray = JSON.parse(msg.content)
|
const txArray = JSON.parse(msg.content)
|
||||||
logger.info(`Msg received with ${txArray.length} Tx to send`)
|
logger.info(`Msg received with ${txArray.length} Tx to send`)
|
||||||
const gasPrice = GasPrice.getPrice()
|
|
||||||
|
|
||||||
const ttl = REDIS_LOCK_TTL * txArray.length
|
const ttl = REDIS_LOCK_TTL * txArray.length
|
||||||
|
|
||||||
@ -114,6 +113,7 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) {
|
|||||||
logger.debug(`Sending ${txArray.length} transactions`)
|
logger.debug(`Sending ${txArray.length} transactions`)
|
||||||
await syncForEach(txArray, async job => {
|
await syncForEach(txArray, async job => {
|
||||||
const gasLimit = addExtraGas(job.gasEstimate, EXTRA_GAS_PERCENTAGE)
|
const gasLimit = addExtraGas(job.gasEstimate, EXTRA_GAS_PERCENTAGE)
|
||||||
|
const gasPrice = GasPrice.getPrice(job.gasPriceOptions)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
logger.info(`Sending transaction with nonce ${nonce}`)
|
logger.info(`Sending transaction with nonce ${nonce}`)
|
||||||
@ -121,7 +121,7 @@ async function main({ msg, ackMsg, nackMsg, sendToQueue, channel }) {
|
|||||||
chain: config.id,
|
chain: config.id,
|
||||||
data: job.data,
|
data: job.data,
|
||||||
nonce,
|
nonce,
|
||||||
gasPrice: gasPrice.toString(10),
|
gasPrice,
|
||||||
amount: '0',
|
amount: '0',
|
||||||
gasLimit,
|
gasLimit,
|
||||||
privateKey: VALIDATOR_ADDRESS_PRIVATE_KEY,
|
privateKey: VALIDATOR_ADDRESS_PRIVATE_KEY,
|
||||||
|
@ -7,7 +7,11 @@ const logger = require('../services/logger').child({
|
|||||||
module: 'gasPrice'
|
module: 'gasPrice'
|
||||||
})
|
})
|
||||||
const { setIntervalAndRun } = require('../utils/utils')
|
const { setIntervalAndRun } = require('../utils/utils')
|
||||||
const { DEFAULT_UPDATE_INTERVAL, GAS_PRICE_BOUNDARIES } = require('../utils/constants')
|
const {
|
||||||
|
DEFAULT_UPDATE_INTERVAL,
|
||||||
|
GAS_PRICE_BOUNDARIES,
|
||||||
|
GAS_PRICE_OPTIONS
|
||||||
|
} = require('../utils/constants')
|
||||||
|
|
||||||
const HomeABI = bridgeConfig.homeBridgeAbi
|
const HomeABI = bridgeConfig.homeBridgeAbi
|
||||||
const ForeignABI = bridgeConfig.foreignBridgeAbi
|
const ForeignABI = bridgeConfig.foreignBridgeAbi
|
||||||
@ -30,6 +34,7 @@ const homeBridge = new web3Home.eth.Contract(HomeABI, HOME_BRIDGE_ADDRESS)
|
|||||||
const foreignBridge = new web3Foreign.eth.Contract(ForeignABI, FOREIGN_BRIDGE_ADDRESS)
|
const foreignBridge = new web3Foreign.eth.Contract(ForeignABI, FOREIGN_BRIDGE_ADDRESS)
|
||||||
|
|
||||||
let cachedGasPrice = null
|
let cachedGasPrice = null
|
||||||
|
let cachedGasPriceOracleSpeeds = null
|
||||||
|
|
||||||
function gasPriceWithinLimits(gasPrice) {
|
function gasPriceWithinLimits(gasPrice) {
|
||||||
if (gasPrice < GAS_PRICE_BOUNDARIES.MIN) {
|
if (gasPrice < GAS_PRICE_BOUNDARIES.MIN) {
|
||||||
@ -49,13 +54,19 @@ async function fetchGasPriceFromOracle(oracleUrl, speedType) {
|
|||||||
throw new Error(`Response from Oracle didn't include gas price for ${speedType} type.`)
|
throw new Error(`Response from Oracle didn't include gas price for ${speedType} type.`)
|
||||||
}
|
}
|
||||||
const gasPrice = gasPriceWithinLimits(oracleGasPrice)
|
const gasPrice = gasPriceWithinLimits(oracleGasPrice)
|
||||||
return Web3Utils.toWei(gasPrice.toString(), 'gwei')
|
return {
|
||||||
|
oracleGasPrice: Web3Utils.toWei(gasPrice.toString(), 'gwei'),
|
||||||
|
oracleResponse: json
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchGasPrice({ bridgeContract, oracleFn }) {
|
async function fetchGasPrice({ bridgeContract, oracleFn }) {
|
||||||
let gasPrice = null
|
let gasPrice = null
|
||||||
|
let oracleGasPriceSpeeds = null
|
||||||
try {
|
try {
|
||||||
gasPrice = await oracleFn()
|
const { oracleGasPrice, oracleResponse } = await oracleFn()
|
||||||
|
gasPrice = oracleGasPrice
|
||||||
|
oracleGasPriceSpeeds = oracleResponse
|
||||||
logger.debug({ gasPrice }, 'Gas price updated using the oracle')
|
logger.debug({ gasPrice }, 'Gas price updated using the oracle')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(`Gas Price API is not available. ${e.message}`)
|
logger.error(`Gas Price API is not available. ${e.message}`)
|
||||||
@ -67,7 +78,10 @@ async function fetchGasPrice({ bridgeContract, oracleFn }) {
|
|||||||
logger.error(`There was a problem getting the gas price from the contract. ${e.message}`)
|
logger.error(`There was a problem getting the gas price from the contract. ${e.message}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return gasPrice
|
return {
|
||||||
|
gasPrice,
|
||||||
|
oracleGasPriceSpeeds
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let fetchGasPriceInterval = null
|
let fetchGasPriceInterval = null
|
||||||
@ -98,21 +112,36 @@ async function start(chainId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchGasPriceInterval = setIntervalAndRun(async () => {
|
fetchGasPriceInterval = setIntervalAndRun(async () => {
|
||||||
const gasPrice = await fetchGasPrice({
|
const { gasPrice, oracleGasPriceSpeeds } = await fetchGasPrice({
|
||||||
bridgeContract,
|
bridgeContract,
|
||||||
oracleFn: () => fetchGasPriceFromOracle(oracleUrl, speedType)
|
oracleFn: () => fetchGasPriceFromOracle(oracleUrl, speedType)
|
||||||
})
|
})
|
||||||
cachedGasPrice = gasPrice || cachedGasPrice
|
cachedGasPrice = gasPrice || cachedGasPrice
|
||||||
|
cachedGasPriceOracleSpeeds = oracleGasPriceSpeeds || cachedGasPriceOracleSpeeds
|
||||||
}, updateInterval)
|
}, updateInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPrice() {
|
function getPrice(options) {
|
||||||
return cachedGasPrice
|
return processGasPriceOptions({ options, cachedGasPrice, cachedGasPriceOracleSpeeds })
|
||||||
|
}
|
||||||
|
|
||||||
|
function processGasPriceOptions({ options, cachedGasPrice, cachedGasPriceOracleSpeeds }) {
|
||||||
|
let gasPrice = cachedGasPrice
|
||||||
|
if (options && options.type && options.value) {
|
||||||
|
if (options.type === GAS_PRICE_OPTIONS.GAS_PRICE) {
|
||||||
|
return options.value
|
||||||
|
} else if (options.type === GAS_PRICE_OPTIONS.SPEED) {
|
||||||
|
const speedOption = cachedGasPriceOracleSpeeds[options.value]
|
||||||
|
gasPrice = speedOption ? Web3Utils.toWei(speedOption.toString(), 'gwei') : cachedGasPrice
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gasPrice
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
start,
|
start,
|
||||||
fetchGasPrice,
|
fetchGasPrice,
|
||||||
getPrice,
|
getPrice,
|
||||||
|
processGasPriceOptions,
|
||||||
gasPriceWithinLimits
|
gasPriceWithinLimits
|
||||||
}
|
}
|
||||||
|
@ -20,5 +20,16 @@ module.exports = {
|
|||||||
ERC_TYPES: {
|
ERC_TYPES: {
|
||||||
ERC20: 'ERC20',
|
ERC20: 'ERC20',
|
||||||
ERC677: 'ERC677'
|
ERC677: 'ERC677'
|
||||||
|
},
|
||||||
|
GAS_PRICE_OPTIONS: {
|
||||||
|
UNDEFINED: '00',
|
||||||
|
GAS_PRICE: '01',
|
||||||
|
SPEED: '02'
|
||||||
|
},
|
||||||
|
ORACLE_GAS_PRICE_SPEEDS: {
|
||||||
|
SLOW: 'slow',
|
||||||
|
STANDARD: 'standard',
|
||||||
|
FAST: 'fast',
|
||||||
|
INSTANT: 'instant'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
const Web3Utils = require('web3-utils')
|
const Web3Utils = require('web3-utils')
|
||||||
|
const { ORACLE_GAS_PRICE_SPEEDS, GAS_PRICE_OPTIONS } = require('./constants')
|
||||||
|
|
||||||
|
const gasPriceSpeedMapper = {
|
||||||
|
'01': ORACLE_GAS_PRICE_SPEEDS.INSTANT,
|
||||||
|
'02': ORACLE_GAS_PRICE_SPEEDS.FAST,
|
||||||
|
'03': ORACLE_GAS_PRICE_SPEEDS.STANDARD,
|
||||||
|
'04': ORACLE_GAS_PRICE_SPEEDS.SLOW
|
||||||
|
}
|
||||||
// strips leading "0x" if present
|
// strips leading "0x" if present
|
||||||
function strip0x(input) {
|
function strip0x(input) {
|
||||||
return input.replace(/^0x/, '')
|
return input.replace(/^0x/, '')
|
||||||
@ -72,8 +79,55 @@ function signatureToVRS(signature) {
|
|||||||
return { v, r, s }
|
return { v, r, s }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addTxHashToData({ encodedData, transactionHash }) {
|
||||||
|
return encodedData.slice(0, 82) + strip0x(transactionHash) + encodedData.slice(82)
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseAMBMessage(message) {
|
||||||
|
message = strip0x(message)
|
||||||
|
|
||||||
|
const sender = `0x${message.slice(0, 40)}`
|
||||||
|
const executor = `0x${message.slice(40, 80)}`
|
||||||
|
const txHash = `0x${message.slice(80, 144)}`
|
||||||
|
const gasLimit = Web3Utils.toBN(message.slice(144, 208))
|
||||||
|
const dataType = message.slice(208, 210)
|
||||||
|
let gasPrice = null
|
||||||
|
let gasPriceSpeed = null
|
||||||
|
let dataStart = 210
|
||||||
|
|
||||||
|
switch (dataType) {
|
||||||
|
case GAS_PRICE_OPTIONS.GAS_PRICE:
|
||||||
|
gasPrice = Web3Utils.toBN(message.slice(210, 274))
|
||||||
|
dataStart += 64
|
||||||
|
break
|
||||||
|
case GAS_PRICE_OPTIONS.SPEED:
|
||||||
|
gasPriceSpeed = gasPriceSpeedMapper[message.slice(210, 212)]
|
||||||
|
dataStart += 2
|
||||||
|
break
|
||||||
|
case GAS_PRICE_OPTIONS.UNDEFINED:
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = `0x${message.slice(dataStart, message.length)}`
|
||||||
|
|
||||||
|
return {
|
||||||
|
sender,
|
||||||
|
executor,
|
||||||
|
txHash,
|
||||||
|
gasLimit,
|
||||||
|
dataType,
|
||||||
|
gasPrice,
|
||||||
|
gasPriceSpeed,
|
||||||
|
data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createMessage,
|
createMessage,
|
||||||
parseMessage,
|
parseMessage,
|
||||||
signatureToVRS
|
signatureToVRS,
|
||||||
|
addTxHashToData,
|
||||||
|
parseAMBMessage,
|
||||||
|
strip0x
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const BigNumber = require('bignumber.js')
|
const BigNumber = require('bignumber.js')
|
||||||
const promiseRetry = require('promise-retry')
|
const promiseRetry = require('promise-retry')
|
||||||
const Web3 = require('web3')
|
const Web3 = require('web3')
|
||||||
|
const { GAS_PRICE_OPTIONS } = require('./constants')
|
||||||
|
|
||||||
async function syncForEach(array, callback) {
|
async function syncForEach(array, callback) {
|
||||||
for (let index = 0; index < array.length; index++) {
|
for (let index = 0; index < array.length; index++) {
|
||||||
@ -96,6 +97,22 @@ function privateKeyToAddress(privateKey) {
|
|||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateGasPriceOptions({ dataType, gasPrice, gasPriceSpeed }) {
|
||||||
|
let gasPriceOptions = null
|
||||||
|
if (dataType === GAS_PRICE_OPTIONS.GAS_PRICE) {
|
||||||
|
gasPriceOptions = {
|
||||||
|
type: dataType,
|
||||||
|
value: gasPrice
|
||||||
|
}
|
||||||
|
} else if (dataType === GAS_PRICE_OPTIONS.SPEED) {
|
||||||
|
gasPriceOptions = {
|
||||||
|
type: dataType,
|
||||||
|
value: gasPriceSpeed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return gasPriceOptions
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
syncForEach,
|
syncForEach,
|
||||||
checkHTTPS,
|
checkHTTPS,
|
||||||
@ -103,5 +120,6 @@ module.exports = {
|
|||||||
addExtraGas,
|
addExtraGas,
|
||||||
setIntervalAndRun,
|
setIntervalAndRun,
|
||||||
watchdog,
|
watchdog,
|
||||||
privateKeyToAddress
|
privateKeyToAddress,
|
||||||
|
generateGasPriceOptions
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,9 @@ const processSignatureRequests = require('./events/processSignatureRequests')(co
|
|||||||
const processCollectedSignatures = require('./events/processCollectedSignatures')(config)
|
const processCollectedSignatures = require('./events/processCollectedSignatures')(config)
|
||||||
const processAffirmationRequests = require('./events/processAffirmationRequests')(config)
|
const processAffirmationRequests = require('./events/processAffirmationRequests')(config)
|
||||||
const processTransfers = require('./events/processTransfers')(config)
|
const processTransfers = require('./events/processTransfers')(config)
|
||||||
|
const processAMBSignatureRequests = require('./events/processAMBSignatureRequests')(config)
|
||||||
|
const processAMBCollectedSignatures = require('./events/processAMBCollectedSignatures')(config)
|
||||||
|
const processAMBAffirmationRequests = require('./events/processAMBAffirmationRequests')(config)
|
||||||
|
|
||||||
const ZERO = toBN(0)
|
const ZERO = toBN(0)
|
||||||
const ONE = toBN(1)
|
const ONE = toBN(1)
|
||||||
@ -100,6 +103,12 @@ function processEvents(events) {
|
|||||||
case 'erc-erc-affirmation-request':
|
case 'erc-erc-affirmation-request':
|
||||||
case 'erc-native-affirmation-request':
|
case 'erc-native-affirmation-request':
|
||||||
return processTransfers(events)
|
return processTransfers(events)
|
||||||
|
case 'amb-signature-request':
|
||||||
|
return processAMBSignatureRequests(events)
|
||||||
|
case 'amb-collected-signatures':
|
||||||
|
return processAMBCollectedSignatures(events)
|
||||||
|
case 'amb-affirmation-request':
|
||||||
|
return processAMBAffirmationRequests(events)
|
||||||
default:
|
default:
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,30 @@
|
|||||||
const sinon = require('sinon')
|
const sinon = require('sinon')
|
||||||
const { expect } = require('chai')
|
const { expect } = require('chai')
|
||||||
const proxyquire = require('proxyquire').noPreserveCache()
|
const proxyquire = require('proxyquire').noPreserveCache()
|
||||||
const { fetchGasPrice, gasPriceWithinLimits } = require('../src/services/gasPrice')
|
const Web3Utils = require('web3-utils')
|
||||||
const { DEFAULT_UPDATE_INTERVAL, GAS_PRICE_BOUNDARIES } = require('../src/utils/constants')
|
const {
|
||||||
|
fetchGasPrice,
|
||||||
|
processGasPriceOptions,
|
||||||
|
gasPriceWithinLimits
|
||||||
|
} = require('../src/services/gasPrice')
|
||||||
|
const {
|
||||||
|
DEFAULT_UPDATE_INTERVAL,
|
||||||
|
GAS_PRICE_OPTIONS,
|
||||||
|
ORACLE_GAS_PRICE_SPEEDS,
|
||||||
|
GAS_PRICE_BOUNDARIES
|
||||||
|
} = require('../src/utils/constants')
|
||||||
|
|
||||||
describe('gasPrice', () => {
|
describe('gasPrice', () => {
|
||||||
describe('fetchGasPrice', () => {
|
describe('fetchGasPrice', () => {
|
||||||
|
const oracleMockResponse = {
|
||||||
|
fast: 17.64,
|
||||||
|
block_time: 13.548,
|
||||||
|
health: true,
|
||||||
|
standard: 10.64,
|
||||||
|
block_number: 6704240,
|
||||||
|
instant: 51.9,
|
||||||
|
slow: 4.4
|
||||||
|
}
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
sinon.stub(console, 'error')
|
sinon.stub(console, 'error')
|
||||||
})
|
})
|
||||||
@ -15,7 +34,11 @@ describe('gasPrice', () => {
|
|||||||
|
|
||||||
it('should fetch the gas price from the oracle by default', async () => {
|
it('should fetch the gas price from the oracle by default', async () => {
|
||||||
// given
|
// given
|
||||||
const oracleFnMock = () => Promise.resolve('1')
|
const oracleFnMock = () =>
|
||||||
|
Promise.resolve({
|
||||||
|
oracleGasPrice: '1',
|
||||||
|
oracleResponse: oracleMockResponse
|
||||||
|
})
|
||||||
const bridgeContractMock = {
|
const bridgeContractMock = {
|
||||||
methods: {
|
methods: {
|
||||||
gasPrice: {
|
gasPrice: {
|
||||||
@ -25,13 +48,14 @@ describe('gasPrice', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const gasPrice = await fetchGasPrice({
|
const { gasPrice, oracleGasPriceSpeeds } = await fetchGasPrice({
|
||||||
bridgeContract: bridgeContractMock,
|
bridgeContract: bridgeContractMock,
|
||||||
oracleFn: oracleFnMock
|
oracleFn: oracleFnMock
|
||||||
})
|
})
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(gasPrice).to.equal('1')
|
expect(gasPrice).to.equal('1')
|
||||||
|
expect(oracleGasPriceSpeeds).to.equal(oracleMockResponse)
|
||||||
})
|
})
|
||||||
it('should fetch the gas price from the contract if the oracle fails', async () => {
|
it('should fetch the gas price from the contract if the oracle fails', async () => {
|
||||||
// given
|
// given
|
||||||
@ -45,13 +69,14 @@ describe('gasPrice', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const gasPrice = await fetchGasPrice({
|
const { gasPrice, oracleGasPriceSpeeds } = await fetchGasPrice({
|
||||||
bridgeContract: bridgeContractMock,
|
bridgeContract: bridgeContractMock,
|
||||||
oracleFn: oracleFnMock
|
oracleFn: oracleFnMock
|
||||||
})
|
})
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(gasPrice).to.equal('2')
|
expect(gasPrice).to.equal('2')
|
||||||
|
expect(oracleGasPriceSpeeds).to.equal(null)
|
||||||
})
|
})
|
||||||
it('should return null if both the oracle and the contract fail', async () => {
|
it('should return null if both the oracle and the contract fail', async () => {
|
||||||
// given
|
// given
|
||||||
@ -65,13 +90,14 @@ describe('gasPrice', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const gasPrice = await fetchGasPrice({
|
const { gasPrice, oracleGasPriceSpeeds } = await fetchGasPrice({
|
||||||
bridgeContract: bridgeContractMock,
|
bridgeContract: bridgeContractMock,
|
||||||
oracleFn: oracleFnMock
|
oracleFn: oracleFnMock
|
||||||
})
|
})
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(gasPrice).to.equal(null)
|
expect(gasPrice).to.equal(null)
|
||||||
|
expect(oracleGasPriceSpeeds).to.equal(null)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe('start', () => {
|
describe('start', () => {
|
||||||
@ -176,4 +202,86 @@ describe('gasPrice', () => {
|
|||||||
expect(gasPrice).to.equal(GAS_PRICE_BOUNDARIES.MAX)
|
expect(gasPrice).to.equal(GAS_PRICE_BOUNDARIES.MAX)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
describe('processGasPriceOptions', () => {
|
||||||
|
const oracleMockResponse = {
|
||||||
|
fast: 17.64,
|
||||||
|
block_time: 13.548,
|
||||||
|
health: true,
|
||||||
|
standard: 10.64,
|
||||||
|
block_number: 6704240,
|
||||||
|
instant: 51.9,
|
||||||
|
slow: 4.4
|
||||||
|
}
|
||||||
|
it('should return cached gas price if no options provided', async () => {
|
||||||
|
// given
|
||||||
|
const options = {}
|
||||||
|
const cachedGasPrice = '1000000000'
|
||||||
|
|
||||||
|
// when
|
||||||
|
const gasPrice = await processGasPriceOptions({
|
||||||
|
options,
|
||||||
|
cachedGasPrice,
|
||||||
|
cachedGasPriceOracleSpeeds: oracleMockResponse
|
||||||
|
})
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(gasPrice).to.equal(cachedGasPrice)
|
||||||
|
})
|
||||||
|
it('should return gas price provided by options', async () => {
|
||||||
|
// given
|
||||||
|
const options = {
|
||||||
|
type: GAS_PRICE_OPTIONS.GAS_PRICE,
|
||||||
|
value: '3000000000'
|
||||||
|
}
|
||||||
|
const cachedGasPrice = '1000000000'
|
||||||
|
|
||||||
|
// when
|
||||||
|
const gasPrice = await processGasPriceOptions({
|
||||||
|
options,
|
||||||
|
cachedGasPrice,
|
||||||
|
cachedGasPriceOracleSpeeds: oracleMockResponse
|
||||||
|
})
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(gasPrice).to.equal(options.value)
|
||||||
|
})
|
||||||
|
it('should return gas price provided by oracle speed option', async () => {
|
||||||
|
// given
|
||||||
|
const options = {
|
||||||
|
type: GAS_PRICE_OPTIONS.SPEED,
|
||||||
|
value: ORACLE_GAS_PRICE_SPEEDS.STANDARD
|
||||||
|
}
|
||||||
|
const cachedGasPrice = '1000000000'
|
||||||
|
const oracleGasPriceGwei = oracleMockResponse[ORACLE_GAS_PRICE_SPEEDS.STANDARD]
|
||||||
|
const oracleGasPrice = Web3Utils.toWei(oracleGasPriceGwei.toString(), 'gwei')
|
||||||
|
|
||||||
|
// when
|
||||||
|
const gasPrice = await processGasPriceOptions({
|
||||||
|
options,
|
||||||
|
cachedGasPrice,
|
||||||
|
cachedGasPriceOracleSpeeds: oracleMockResponse
|
||||||
|
})
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(gasPrice).to.equal(oracleGasPrice)
|
||||||
|
})
|
||||||
|
it('should return cached gas price if invalid speed option', async () => {
|
||||||
|
// given
|
||||||
|
const options = {
|
||||||
|
type: GAS_PRICE_OPTIONS.SPEED,
|
||||||
|
value: 'unknown'
|
||||||
|
}
|
||||||
|
const cachedGasPrice = '1000000000'
|
||||||
|
|
||||||
|
// when
|
||||||
|
const gasPrice = await processGasPriceOptions({
|
||||||
|
options,
|
||||||
|
cachedGasPrice,
|
||||||
|
cachedGasPriceOracleSpeeds: oracleMockResponse
|
||||||
|
})
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(gasPrice).to.equal(cachedGasPrice)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
const { BN, toBN } = require('web3').utils
|
const { BN, toBN } = require('web3').utils
|
||||||
const { expect } = require('chai').use(require('bn-chai')(BN))
|
const { expect } = require('chai').use(require('bn-chai')(BN))
|
||||||
const { createMessage, parseMessage, signatureToVRS } = require('../src/utils/message')
|
const {
|
||||||
|
createMessage,
|
||||||
|
parseMessage,
|
||||||
|
signatureToVRS,
|
||||||
|
parseAMBMessage,
|
||||||
|
strip0x
|
||||||
|
} = require('../src/utils/message')
|
||||||
|
const { ORACLE_GAS_PRICE_SPEEDS } = require('../src/utils/constants')
|
||||||
|
|
||||||
describe('message utils', () => {
|
describe('message utils', () => {
|
||||||
const expectedMessageLength = 104
|
const expectedMessageLength = 104
|
||||||
@ -293,4 +300,107 @@ describe('message utils', () => {
|
|||||||
expect(signatureThunk).to.throw()
|
expect(signatureThunk).to.throw()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
describe('parseAMBMessage', () => {
|
||||||
|
it('should parse data type 00', () => {
|
||||||
|
const msgSender = '0x003667154bb32e42bb9e1e6532f19d187fa0082e'
|
||||||
|
const msgExecutor = '0xf4bef13f9f4f2b203faf0c3cbbaabe1afe056955'
|
||||||
|
const msgTxHash = '0xbdceda9d8c94838aca10c687da1411a07b1390e88239c0638cb9cc264219cc10'
|
||||||
|
const msgGasLimit = '000000000000000000000000000000000000000000000000000000005b877705'
|
||||||
|
const msgDataType = '00'
|
||||||
|
const msgData = '0xb1591967aed668a4b27645ff40c444892d91bf5951b382995d4d4f6ee3a2ce03'
|
||||||
|
const message = `0x${strip0x(msgSender)}${strip0x(msgExecutor)}${strip0x(
|
||||||
|
msgTxHash
|
||||||
|
)}${msgGasLimit}${msgDataType}${strip0x(msgData)}`
|
||||||
|
|
||||||
|
// when
|
||||||
|
const {
|
||||||
|
sender,
|
||||||
|
executor,
|
||||||
|
txHash,
|
||||||
|
gasLimit,
|
||||||
|
dataType,
|
||||||
|
gasPrice,
|
||||||
|
gasPriceSpeed,
|
||||||
|
data
|
||||||
|
} = parseAMBMessage(message)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(sender).to.be.equal(msgSender)
|
||||||
|
expect(executor).to.be.equal(msgExecutor)
|
||||||
|
expect(txHash).to.be.equal(msgTxHash)
|
||||||
|
expect(gasLimit).to.eq.BN(toBN(msgGasLimit))
|
||||||
|
expect(dataType).to.be.equal(msgDataType)
|
||||||
|
expect(gasPrice).to.be.equal(null)
|
||||||
|
expect(gasPriceSpeed).to.be.equal(null)
|
||||||
|
expect(data).to.be.equal(msgData)
|
||||||
|
})
|
||||||
|
it('should parse data type 01', () => {
|
||||||
|
const msgSender = '0x003667154bb32e42bb9e1e6532f19d187fa0082e'
|
||||||
|
const msgExecutor = '0xf4bef13f9f4f2b203faf0c3cbbaabe1afe056955'
|
||||||
|
const msgTxHash = '0xbdceda9d8c94838aca10c687da1411a07b1390e88239c0638cb9cc264219cc10'
|
||||||
|
const msgGasLimit = '000000000000000000000000000000000000000000000000000000005b877705'
|
||||||
|
const msgDataType = '01'
|
||||||
|
const msgGasPrice = '0000000000000000000000000000000000000000000000000000000165a0bc00'
|
||||||
|
const msgData = '0xb1591967aed668a4b27645ff40c444892d91bf5951b382995d4d4f6ee3a2ce03'
|
||||||
|
const message = `0x${strip0x(msgSender)}${strip0x(msgExecutor)}${strip0x(
|
||||||
|
msgTxHash
|
||||||
|
)}${msgGasLimit}${msgDataType}${msgGasPrice}${strip0x(msgData)}`
|
||||||
|
|
||||||
|
// when
|
||||||
|
const {
|
||||||
|
sender,
|
||||||
|
executor,
|
||||||
|
txHash,
|
||||||
|
gasLimit,
|
||||||
|
dataType,
|
||||||
|
gasPrice,
|
||||||
|
gasPriceSpeed,
|
||||||
|
data
|
||||||
|
} = parseAMBMessage(message)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(sender).to.be.equal(msgSender)
|
||||||
|
expect(executor).to.be.equal(msgExecutor)
|
||||||
|
expect(txHash).to.be.equal(msgTxHash)
|
||||||
|
expect(gasLimit).to.eq.BN(toBN(msgGasLimit))
|
||||||
|
expect(dataType).to.be.equal(msgDataType)
|
||||||
|
expect(gasPrice).to.eq.BN(toBN(msgGasPrice))
|
||||||
|
expect(gasPriceSpeed).to.be.equal(null)
|
||||||
|
expect(data).to.be.equal(msgData)
|
||||||
|
})
|
||||||
|
it('should parse data type 02', () => {
|
||||||
|
const msgSender = '0x003667154bb32e42bb9e1e6532f19d187fa0082e'
|
||||||
|
const msgExecutor = '0xf4bef13f9f4f2b203faf0c3cbbaabe1afe056955'
|
||||||
|
const msgTxHash = '0xbdceda9d8c94838aca10c687da1411a07b1390e88239c0638cb9cc264219cc10'
|
||||||
|
const msgGasLimit = '000000000000000000000000000000000000000000000000000000005b877705'
|
||||||
|
const msgDataType = '02'
|
||||||
|
const msgGasPriceSpeed = '0x03'
|
||||||
|
const msgData = '0xb1591967aed668a4b27645ff40c444892d91bf5951b382995d4d4f6ee3a2ce03'
|
||||||
|
const message = `0x${strip0x(msgSender)}${strip0x(msgExecutor)}${strip0x(
|
||||||
|
msgTxHash
|
||||||
|
)}${msgGasLimit}${msgDataType}${strip0x(msgGasPriceSpeed)}${strip0x(msgData)}`
|
||||||
|
|
||||||
|
// when
|
||||||
|
const {
|
||||||
|
sender,
|
||||||
|
executor,
|
||||||
|
txHash,
|
||||||
|
gasLimit,
|
||||||
|
dataType,
|
||||||
|
gasPrice,
|
||||||
|
gasPriceSpeed,
|
||||||
|
data
|
||||||
|
} = parseAMBMessage(message)
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(sender).to.be.equal(msgSender)
|
||||||
|
expect(executor).to.be.equal(msgExecutor)
|
||||||
|
expect(txHash).to.be.equal(msgTxHash)
|
||||||
|
expect(gasLimit).to.eq.BN(toBN(msgGasLimit))
|
||||||
|
expect(dataType).to.be.equal(msgDataType)
|
||||||
|
expect(gasPrice).to.be.equal(null)
|
||||||
|
expect(gasPriceSpeed).to.be.equal(ORACLE_GAS_PRICE_SPEEDS.STANDARD)
|
||||||
|
expect(data).to.be.equal(msgData)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -3,7 +3,8 @@ const chai = require('chai')
|
|||||||
const chaiAsPromised = require('chai-as-promised')
|
const chaiAsPromised = require('chai-as-promised')
|
||||||
const BigNumber = require('bignumber.js')
|
const BigNumber = require('bignumber.js')
|
||||||
const proxyquire = require('proxyquire')
|
const proxyquire = require('proxyquire')
|
||||||
const { addExtraGas, syncForEach } = require('../src/utils/utils')
|
const { addExtraGas, syncForEach, generateGasPriceOptions } = require('../src/utils/utils')
|
||||||
|
const { GAS_PRICE_OPTIONS, ORACLE_GAS_PRICE_SPEEDS } = require('../src/utils/constants')
|
||||||
|
|
||||||
chai.use(chaiAsPromised)
|
chai.use(chaiAsPromised)
|
||||||
const { expect } = chai
|
const { expect } = chai
|
||||||
@ -134,4 +135,54 @@ describe('utils', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
describe('generateGasPriceOptions', () => {
|
||||||
|
it('should work for GAS_PRICE option', () => {
|
||||||
|
// given
|
||||||
|
const dataType = GAS_PRICE_OPTIONS.GAS_PRICE
|
||||||
|
const gasPrice = BigNumber('0000000000000000000000000000000000000000000000000000000165a0bc00')
|
||||||
|
const gasPriceSpeed = null
|
||||||
|
|
||||||
|
const expectedResult = {
|
||||||
|
type: dataType,
|
||||||
|
value: gasPrice
|
||||||
|
}
|
||||||
|
|
||||||
|
// when
|
||||||
|
const gasPriceOptions = generateGasPriceOptions({ dataType, gasPrice, gasPriceSpeed })
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(gasPriceOptions.type).to.be.equal(expectedResult.type)
|
||||||
|
expect(gasPriceOptions.value).to.be.equal(expectedResult.value)
|
||||||
|
})
|
||||||
|
it('should work for SPEED option', () => {
|
||||||
|
// given
|
||||||
|
const dataType = GAS_PRICE_OPTIONS.SPEED
|
||||||
|
const gasPrice = null
|
||||||
|
const gasPriceSpeed = ORACLE_GAS_PRICE_SPEEDS.STANDARD
|
||||||
|
|
||||||
|
const expectedResult = {
|
||||||
|
type: dataType,
|
||||||
|
value: gasPriceSpeed
|
||||||
|
}
|
||||||
|
|
||||||
|
// when
|
||||||
|
const gasPriceOptions = generateGasPriceOptions({ dataType, gasPrice, gasPriceSpeed })
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(gasPriceOptions.type).to.be.equal(expectedResult.type)
|
||||||
|
expect(gasPriceOptions.value).to.be.equal(expectedResult.value)
|
||||||
|
})
|
||||||
|
it('should return null option for undefined option', () => {
|
||||||
|
// given
|
||||||
|
const dataType = GAS_PRICE_OPTIONS.UNDEFINED
|
||||||
|
const gasPrice = null
|
||||||
|
const gasPriceSpeed = null
|
||||||
|
|
||||||
|
// when
|
||||||
|
const gasPriceOptions = generateGasPriceOptions({ dataType, gasPrice, gasPriceSpeed })
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(gasPriceOptions).to.be.equal(null)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user