-
-
Save riordant/226f8882556a5c7981b239e4e5d96918 to your computer and use it in GitHub Desktop.
Solidity wrapper for Ethereum Byzantium's BigInt `modexp` built-in contract 0x5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Wrapper for built-in BigNumber_modexp (contract 0x5) as described here. https://github.com/ethereum/EIPs/pull/198 | |
function modexp(bytes memory _base, bytes memory _exp, bytes memory _mod) internal view returns(bytes memory ret) { | |
assembly { | |
let bl := mload(_base) | |
let el := mload(_exp) | |
let ml := mload(_mod) | |
// Free memory pointer is always stored at 0x40 | |
let freemem := mload(0x40) | |
// arg[0] = base.length @ +0 | |
mstore(freemem, bl) | |
// arg[1] = exp.length @ +32 | |
mstore(add(freemem,32), el) | |
// arg[2] = mod.length @ +64 | |
mstore(add(freemem,64), ml) | |
// arg[3] = base.bits @ + 96 | |
// Use identity built-in (contract 0x4) as a cheap memcpy | |
let success := call(450, 0x4, 0, add(_base,32), bl, add(freemem,96), bl) | |
// arg[4] = exp.bits @ +96+base.length | |
let size := add(96, bl) | |
success := call(450, 0x4, 0, add(_exp,32), el, add(freemem,size), el) | |
// arg[5] = mod.bits @ +96+base.length+exp.length | |
size := add(size,el) | |
success := call(450, 0x4, 0, add(_mod,32), ml, add(freemem,size), ml) | |
// Total size of input = 96+base.length+exp.length+mod.length | |
size := add(size,ml) | |
// Invoke contract 0x5, put return value right after mod.length, @ +96 | |
success := call(sub(gas, 1350), 0x5, 0, freemem, size, add(96,freemem), ml) | |
// point to the location of the return value (length, bits) | |
ret := add(64,freemem) | |
mstore(0x40, add(add(96, freemem),ml)) //deallocate freemem pointer | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks!