Skip to content

Instantly share code, notes, and snippets.

@riordant
Forked from lionello/ModExp.sol
Last active November 15, 2018 13:24
Show Gist options
  • Save riordant/226f8882556a5c7981b239e4e5d96918 to your computer and use it in GitHub Desktop.
Save riordant/226f8882556a5c7981b239e4e5d96918 to your computer and use it in GitHub Desktop.
Solidity wrapper for Ethereum Byzantium's BigInt `modexp` built-in contract 0x5
// 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
}
}
@lionello
Copy link

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment