Initial BLS stub

This commit is contained in:
James Zaki
2021-01-08 15:35:15 +11:00
parent e51b88c1f1
commit fac41ec66e
11 changed files with 1268 additions and 38 deletions

48
contracts/BLSWallet.sol Normal file
View File

@@ -0,0 +1,48 @@
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
pragma abicoder v2;
import "./lib/BLS.sol";
import "./lib/IERC20.sol";
import "hardhat/console.sol";
contract BLSWallet //is IERC20 //(to consider?)
{
IERC20 baseToken;
mapping (address => uint256[4])public blsKeys;
mapping (address => uint256) balances;
constructor(IERC20 token) {
baseToken = token;
}
/**
@dev Called from token holder's address
*/
function deposit(
uint256[4] memory blsPubKey,
uint256 amount
) public {
// TODO: check existing key
baseToken.transferFrom(msg.sender, address(this), amount);
blsKeys[msg.sender] = blsPubKey;
balances[msg.sender] += amount;
}
function withdraw() public {
uint256 amount = balances[msg.sender];
blsKeys[msg.sender] = [0,0,0,0];
balances[msg.sender] = 0;
baseToken.transfer(msg.sender, amount);
}
// //TODO: verifyMultiple
// function transferBatch() {}
function balanceOf(address account) public view returns (uint256) {
return balances[account];
}
}

View File

@@ -1,23 +0,0 @@
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.7.0;
import "hardhat/console.sol";
contract Greeter {
string greeting;
constructor(string memory _greeting) {
console.log("Deploying a Greeter with greeting:", _greeting);
greeting = _greeting;
}
function greet() public view returns (string memory) {
return greeting;
}
function setGreeting(string memory _greeting) public {
console.log("Changing greeting from '%s' to '%s'", greeting, _greeting);
greeting = _greeting;
}
}

437
contracts/lib/BLS.sol Normal file
View File

@@ -0,0 +1,437 @@
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
import { ModexpInverse, ModexpSqrt } from "./ModExp.sol";
/**
@title BonehLynnShacham (BLS) signature scheme on Barreto-Naehrig 254 bit curve (BN-254)
@notice We use BLS signature aggregation to reduce the size of signature data to store on chain.
@dev We use G1 points for signatures and messages, and G2 points for public keys
*/
library BLS {
// Field order
// prettier-ignore
uint256 private constant N = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
// Negated genarator of G2
// prettier-ignore
uint256 private constant N_G2_X1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
// prettier-ignore
uint256 private constant N_G2_X0 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
// prettier-ignore
uint256 private constant N_G2_Y1 = 17805874995975841540914202342111839520379459829704422454583296818431106115052;
// prettier-ignore
uint256 private constant N_G2_Y0 = 13392588948715843804641432497768002650278120570034223513918757245338268106653;
// sqrt(-3)
// prettier-ignore
uint256 private constant Z0 = 0x0000000000000000b3c4d79d41a91759a9e4c7e359b6b89eaec68e62effffffd;
// (sqrt(-3) - 1) / 2
// prettier-ignore
uint256 private constant Z1 = 0x000000000000000059e26bcea0d48bacd4f263f1acdb5c4f5763473177fffffe;
// prettier-ignore
uint256 private constant T24 = 0x1000000000000000000000000000000000000000000000000;
// prettier-ignore
uint256 private constant MASK24 = 0xffffffffffffffffffffffffffffffffffffffffffffffff;
function verifySingle(
uint256[2] memory signature,
uint256[4] memory pubkey,
uint256[2] memory message
) internal view returns (bool, bool) {
uint256[12] memory input = [
signature[0],
signature[1],
N_G2_X1,
N_G2_X0,
N_G2_Y1,
N_G2_Y0,
message[0],
message[1],
pubkey[1],
pubkey[0],
pubkey[3],
pubkey[2]
];
uint256[1] memory out;
uint256 precompileGasCost = pairingPrecompileCallGasCost(2);
bool callSuccess;
// solium-disable-next-line security/no-inline-assembly
assembly {
callSuccess := staticcall(
precompileGasCost,
8,
input,
384,
out,
0x20
)
}
if (!callSuccess) {
return (false, false);
}
return (out[0] != 0, true);
}
function verifyMultiple(
uint256[2] memory signature,
uint256[4][] memory pubkeys,
uint256[2][] memory messages
) internal view returns (bool checkResult, bool callSuccess) {
uint256 size = pubkeys.length;
require(size > 0, "BLS: number of public key is zero");
require(
size == messages.length,
"BLS: number of public keys and messages must be equal"
);
uint256 inputSize = (size + 1) * 6;
uint256[] memory input = new uint256[](inputSize);
input[0] = signature[0];
input[1] = signature[1];
input[2] = N_G2_X1;
input[3] = N_G2_X0;
input[4] = N_G2_Y1;
input[5] = N_G2_Y0;
for (uint256 i = 0; i < size; i++) {
input[i * 6 + 6] = messages[i][0];
input[i * 6 + 7] = messages[i][1];
input[i * 6 + 8] = pubkeys[i][1];
input[i * 6 + 9] = pubkeys[i][0];
input[i * 6 + 10] = pubkeys[i][3];
input[i * 6 + 11] = pubkeys[i][2];
}
uint256[1] memory out;
uint256 precompileGasCost = pairingPrecompileCallGasCost(size);
// solium-disable-next-line security/no-inline-assembly
assembly {
callSuccess := staticcall(
precompileGasCost,
8,
add(input, 0x20),
mul(inputSize, 0x20),
out,
0x20
)
}
if (!callSuccess) {
return (false, false);
}
return (out[0] != 0, true);
}
function pairingPrecompileCallGasCost(uint256 pubkeyLen)
internal
pure
returns (uint256)
{
uint256 base = 34000;
uint256 pair = 45000;
return base + pair * pubkeyLen;
}
/**
@notice Fouque-Tibouchi Hash to Curve
*/
function hashToPoint(bytes32 domain, bytes memory message)
internal
view
returns (uint256[2] memory)
{
uint256[2] memory u = hashToField(domain, message);
uint256[2] memory p0 = mapToPoint(u[0]);
uint256[2] memory p1 = mapToPoint(u[1]);
uint256[4] memory bnAddInput;
bnAddInput[0] = p0[0];
bnAddInput[1] = p0[1];
bnAddInput[2] = p1[0];
bnAddInput[3] = p1[1];
bool success;
// solium-disable-next-line security/no-inline-assembly
assembly {
success := staticcall(sub(gas(), 2000), 6, bnAddInput, 128, p0, 64)
switch success
case 0 {
invalid()
}
}
require(success, "BLS: bn add call failed");
return p0;
}
function mapToPoint(uint256 _x)
internal
pure
returns (uint256[2] memory p)
{
require(_x < N, "mapToPointFT: invalid field element");
uint256 x = _x;
(, bool decision) = sqrt(x);
uint256 a0 = mulmod(x, x, N);
a0 = addmod(a0, 4, N);
uint256 a1 = mulmod(x, Z0, N);
uint256 a2 = mulmod(a1, a0, N);
a2 = inverse(a2);
a1 = mulmod(a1, a1, N);
a1 = mulmod(a1, a2, N);
// x1
a1 = mulmod(x, a1, N);
x = addmod(Z1, N - a1, N);
// check curve
a1 = mulmod(x, x, N);
a1 = mulmod(a1, x, N);
a1 = addmod(a1, 3, N);
bool found;
(a1, found) = sqrt(a1);
if (found) {
if (!decision) {
a1 = N - a1;
}
return [x, a1];
}
// x2
x = N - addmod(x, 1, N);
// check curve
a1 = mulmod(x, x, N);
a1 = mulmod(a1, x, N);
a1 = addmod(a1, 3, N);
(a1, found) = sqrt(a1);
if (found) {
if (!decision) {
a1 = N - a1;
}
return [x, a1];
}
// x3
x = mulmod(a0, a0, N);
x = mulmod(x, x, N);
x = mulmod(x, a2, N);
x = mulmod(x, a2, N);
x = addmod(x, 1, N);
// must be on curve
a1 = mulmod(x, x, N);
a1 = mulmod(a1, x, N);
a1 = addmod(a1, 3, N);
(a1, found) = sqrt(a1);
require(found, "BLS: bad ft mapping implementation");
if (!decision) {
a1 = N - a1;
}
return [x, a1];
}
function isValidSignature(uint256[2] memory signature)
internal
pure
returns (bool)
{
if ((signature[0] >= N) || (signature[1] >= N)) {
return false;
} else {
return isOnCurveG1(signature);
}
}
function isOnCurveG1(uint256[2] memory point)
internal
pure
returns (bool _isOnCurve)
{
// solium-disable-next-line security/no-inline-assembly
assembly {
let t0 := mload(point)
let t1 := mload(add(point, 32))
let t2 := mulmod(t0, t0, N)
t2 := mulmod(t2, t0, N)
t2 := addmod(t2, 3, N)
t1 := mulmod(t1, t1, N)
_isOnCurve := eq(t1, t2)
}
}
function isOnCurveG2(uint256[4] memory point)
internal
pure
returns (bool _isOnCurve)
{
// solium-disable-next-line security/no-inline-assembly
assembly {
// x0, x1
let t0 := mload(point)
let t1 := mload(add(point, 32))
// x0 ^ 2
let t2 := mulmod(t0, t0, N)
// x1 ^ 2
let t3 := mulmod(t1, t1, N)
// 3 * x0 ^ 2
let t4 := add(add(t2, t2), t2)
// 3 * x1 ^ 2
let t5 := addmod(add(t3, t3), t3, N)
// x0 * (x0 ^ 2 - 3 * x1 ^ 2)
t2 := mulmod(add(t2, sub(N, t5)), t0, N)
// x1 * (3 * x0 ^ 2 - x1 ^ 2)
t3 := mulmod(add(t4, sub(N, t3)), t1, N)
// x ^ 3 + b
t0 := addmod(
t2,
0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5,
N
)
t1 := addmod(
t3,
0x009713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2,
N
)
// y0, y1
t2 := mload(add(point, 64))
t3 := mload(add(point, 96))
// y ^ 2
t4 := mulmod(addmod(t2, t3, N), addmod(t2, sub(N, t3), N), N)
t3 := mulmod(shl(1, t2), t3, N)
// y ^ 2 == x ^ 3 + b
_isOnCurve := and(eq(t0, t4), eq(t1, t3))
}
}
function sqrt(uint256 xx) internal pure returns (uint256 x, bool hasRoot) {
x = ModexpSqrt.run(xx);
hasRoot = mulmod(x, x, N) == xx;
}
function inverse(uint256 a) internal pure returns (uint256) {
return ModexpInverse.run(a);
}
function hashToField(bytes32 domain, bytes memory messages)
internal
pure
returns (uint256[2] memory)
{
bytes memory _msg = expandMsgTo96(domain, messages);
uint256 u0;
uint256 u1;
uint256 a0;
uint256 a1;
// solium-disable-next-line security/no-inline-assembly
assembly {
let p := add(_msg, 24)
u1 := and(mload(p), MASK24)
p := add(_msg, 48)
u0 := and(mload(p), MASK24)
a0 := addmod(mulmod(u1, T24, N), u0, N)
p := add(_msg, 72)
u1 := and(mload(p), MASK24)
p := add(_msg, 96)
u0 := and(mload(p), MASK24)
a1 := addmod(mulmod(u1, T24, N), u0, N)
}
return [a0, a1];
}
function expandMsgTo96(bytes32 domain, bytes memory message)
internal
pure
returns (bytes memory)
{
// zero<64>|msg<var>|lib_str<2>|I2OSP(0, 1)<1>|dst<var>|dst_len<1>
uint256 t0 = message.length;
bytes memory msg0 = new bytes(32 + t0 + 64 + 4);
bytes memory out = new bytes(96);
// b0
// solium-disable-next-line security/no-inline-assembly
assembly {
let p := add(msg0, 96)
for {
let z := 0
} lt(z, t0) {
z := add(z, 32)
} {
mstore(add(p, z), mload(add(message, add(z, 32))))
}
p := add(p, t0)
mstore8(p, 0)
p := add(p, 1)
mstore8(p, 96)
p := add(p, 1)
mstore8(p, 0)
p := add(p, 1)
mstore(p, domain)
p := add(p, 32)
mstore8(p, 32)
}
bytes32 b0 = sha256(msg0);
bytes32 bi;
t0 = 32 + 34;
// resize intermediate message
// solium-disable-next-line security/no-inline-assembly
assembly {
mstore(msg0, t0)
}
// b1
// solium-disable-next-line security/no-inline-assembly
assembly {
mstore(add(msg0, 32), b0)
mstore8(add(msg0, 64), 1)
mstore(add(msg0, 65), domain)
mstore8(add(msg0, add(32, 65)), 32)
}
bi = sha256(msg0);
// solium-disable-next-line security/no-inline-assembly
assembly {
mstore(add(out, 32), bi)
}
// b2
// solium-disable-next-line security/no-inline-assembly
assembly {
let t := xor(b0, bi)
mstore(add(msg0, 32), t)
mstore8(add(msg0, 64), 2)
mstore(add(msg0, 65), domain)
mstore8(add(msg0, add(32, 65)), 32)
}
bi = sha256(msg0);
// solium-disable-next-line security/no-inline-assembly
assembly {
mstore(add(out, 64), bi)
}
// b3
// solium-disable-next-line security/no-inline-assembly
assembly {
let t := xor(b0, bi)
mstore(add(msg0, 32), t)
mstore8(add(msg0, 64), 3)
mstore(add(msg0, 65), domain)
mstore8(add(msg0, add(32, 65)), 32)
}
bi = sha256(msg0);
// solium-disable-next-line security/no-inline-assembly
assembly {
mstore(add(out, 96), bi)
}
return out;
}
}

73
contracts/lib/IERC20.sol Normal file
View File

@@ -0,0 +1,73 @@
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}

652
contracts/lib/ModExp.sol Normal file
View File

@@ -0,0 +1,652 @@
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;
/**
@title Compute Inverse by Modular Exponentiation
@notice Compute $input^(N - 2) mod N$ using Addition Chain method.
Where N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47
and N - 2 = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45
@dev the function body is generated with the modified addchain script
see https://github.com/kobigurk/addchain/commit/2c37a2ace567a9bdc680b4e929c94aaaa3ec700f
*/
library ModexpInverse {
function run(uint256 t2) internal pure returns (uint256 t0) {
// solium-disable-next-line security/no-inline-assembly
assembly {
let
n
:= 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47
t0 := mulmod(t2, t2, n)
let t5 := mulmod(t0, t2, n)
let t1 := mulmod(t5, t0, n)
let t3 := mulmod(t5, t5, n)
let t8 := mulmod(t1, t0, n)
let t4 := mulmod(t3, t5, n)
let t6 := mulmod(t3, t1, n)
t0 := mulmod(t3, t3, n)
let t7 := mulmod(t8, t3, n)
t3 := mulmod(t4, t3, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t7, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t1, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t1, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t7, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t1, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t1, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t1, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t1, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t4, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t1, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t7, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t3, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t3, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t4, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t3, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t1, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t1, n)
}
}
}
/**
@title Compute Squre Root by Modular Exponentiation
@notice Compute $input^{(N + 1) / 4} mod N$ using Addition Chain method.
Where N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47
and (N + 1) / 4 = 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52
*/
library ModexpSqrt {
function run(uint256 t6) internal pure returns (uint256 t0) {
// solium-disable-next-line security/no-inline-assembly
assembly {
let
n
:= 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47
t0 := mulmod(t6, t6, n)
let t4 := mulmod(t0, t6, n)
let t2 := mulmod(t4, t0, n)
let t3 := mulmod(t4, t4, n)
let t8 := mulmod(t2, t0, n)
let t1 := mulmod(t3, t4, n)
let t5 := mulmod(t3, t2, n)
t0 := mulmod(t3, t3, n)
let t7 := mulmod(t8, t3, n)
t3 := mulmod(t1, t3, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t4, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t4, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t7, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t4, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t7, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t4, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t4, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t1, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t8, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t7, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t3, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t6, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t4, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t5, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t4, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t4, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t3, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t1, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t3, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t2, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t0, n)
t0 := mulmod(t0, t1, n)
t0 := mulmod(t0, t0, n)
}
}
}

View File

@@ -0,0 +1,18 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MockERC20 is ERC20 {
constructor(
string memory name,
string memory symbol,
uint256 supply
) public ERC20(name, symbol) {
_mint(msg.sender, supply);
}
function mint(address _to, uint256 _amount) public {
_mint(_to, _amount);
}
}

View File

@@ -17,6 +17,15 @@ task("accounts", "Prints the list of accounts", async () => {
* @type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: "0.7.3",
solidity: {
compilers: [
{
version: "0.8.0"
},
{
version: "0.7.0"
}
]
}
};

View File

@@ -6,5 +6,8 @@
"ethereum-waffle": "^3.0.0",
"ethers": "^5.0.0",
"hardhat": "^2.0.7"
},
"dependencies": {
"@openzeppelin/contracts": "^3.3.0"
}
}

22
test/blsWallet-test.js Normal file
View File

@@ -0,0 +1,22 @@
const { expect } = require("chai");
const { ethers } = require("hardhat");
const acc1BLSPubKey = [0xAA, 0xBB, 0xCC, 0xDD];
const acc2BLSPubKey = [0xEE, 0xFF, 0x00, 0x11];
const initialSupply = ethers.utils.parseUnits("1000000")
describe('BLSWallet', async function () {
beforeEach(async function () {
[admin, account1, account2] = await ethers.getSigners();
const MockERC20 = await ethers.getContractFactory("MockERC20");
this.baseToken = await MockERC20.deploy("AnyToken","TOK", initialSupply);
const BLSWallet = await ethers.getContractFactory("BLSWallet");
this.blsWallet = await BLSWallet.deploy(this.baseToken.address);
});
it('should ', async function () {
await this.blsWallet.connect(account1).deposit(acc1BLSPubKey, 0);
});
});

View File

@@ -1,14 +0,0 @@
const { expect } = require("chai");
describe("Greeter", function() {
it("Should return the new greeting once it's changed", async function() {
const Greeter = await ethers.getContractFactory("Greeter");
const greeter = await Greeter.deploy("Hello, world!");
await greeter.deployed();
expect(await greeter.greet()).to.equal("Hello, world!");
await greeter.setGreeting("Hola, mundo!");
expect(await greeter.greet()).to.equal("Hola, mundo!");
});
});

View File

@@ -453,6 +453,11 @@
"@types/sinon-chai" "^3.2.3"
"@types/web3" "1.0.19"
"@openzeppelin/contracts@^3.3.0":
version "3.3.0"
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-3.3.0.tgz#ffdb693c5c349fc33bba420248dd3ac0a2d7c408"
integrity sha512-AemZEsQYtUp1WRkcmZm1div5ORfTpLquLaziCIrSagjxyKdmObxuaY1yjQ5SHFMctR8rLwp706NXTbiIRJg7pw==
"@resolver-engine/core@^0.3.3":
version "0.3.3"
resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967"