Commit 72c56b8e authored by John Doe's avatar John Doe
Browse files

Upload Client.

parent 13d5f931
Pipeline #6 canceled with stages
PRIVATE_KEY=
INFURA_PROJECT_ID=
COINMARKETCAP_API_KEY=
ETHERSCAN_API_KEY=
BSC_API_KEY=
\ No newline at end of file
# Pilot Client
# README #
This README would normally document whatever steps are necessary to get your application up and running.
### What is this repository for? ###
* Quick summary
* Version
* [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo)
### How do I get set up? ###
* Summary of set up
* Configuration
* Dependencies
* Database configuration
* How to run tests
* Deployment instructions
### Contribution guidelines ###
* Writing tests
* Code review
* Other guidelines
### Who do I talk to? ###
* Repo owner or admin
* Other community or team contact
\ No newline at end of file
module.exports = [
// "0x97c35747AbE05EFD38A1Fc081a42600fdfB1e2F1", // xft token address
// "0xA542a8Ed9E40eb6C39Dcc0b7d3293BA174C8DbE1", // price consumer address
];
// SPDX-License-Identifier: MIT
pragma solidity =0.8.4;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./SchnorrSignature.sol";
import "./interfaces/IERC20MintableBurnable.sol";
import "./interfaces/IPriceConsumer.sol";
contract CommitmentCircuit is SchnorrSignature {
using SafeERC20 for IERC20;
enum Assets {
XFT,
USD,
BTC,
ETH,
XAU
}
struct CommitmentDetails {
PointEC commitment;
Assets asset;
}
IERC20MintableBurnable public xftTokenAddress;
IPriceConsumer public priceConsumer;
event CommitmentTransferred(
address indexed sender,
address indexed recipient,
uint256 senderCommitmentId,
uint256 recipientCommitmentId,
PointEC senderCommitment,
PointEC recipientCommitment
);
event Deposited(
address indexed to,
uint256 amount,
uint256 indexed commitmentId,
PointEC commitment
);
event Withdrawn(
address indexed to,
uint256 amount,
uint256 indexed commitmentIdOld,
PointEC commitmentOld
);
event Excessed(address indexed to, uint256 indexed commitmentId, PointEC commitment);
event Grouped(address indexed to, uint256 indexed id, PointEC commitment);
// todo: public is temporary
mapping(address => uint256[]) public _idsByAddress;
mapping(address => mapping(uint256 => CommitmentDetails)) public _commitmentById;
mapping(address => mapping(uint256 => bool)) public _spents;
constructor(address _xftTokenAddress, address _priceConsumer) {
require(_xftTokenAddress != address(0), "Token address not be zero");
require(_priceConsumer != address(0), "Price consumer address not be zero");
xftTokenAddress = IERC20MintableBurnable(_xftTokenAddress);
priceConsumer = IPriceConsumer(_priceConsumer);
}
/**
* @dev Transfer commitment between users.
* @param recipient address of commitment recipient.
* @param senderCommitmentId id of the sending commitment.
* @param recipientCommitment new commitment that will be received by recipient:
commitment - new commitment
asset - asset of commitment.
* @param excessCommitment Commitment for excess amount.
* @param senderPubKey Sender's public key.
* @param recipientPubKey Recipient's public key.
* @param excessPubKey Public key for excess amount.
* @param schnorrSignatureSet Set of Schnorr params:
* message - Signed message
* pubKey - Public key with which message was signed
* ecR - Signature part R
* s - Signature part s.
*/
function complexTransferCommitment(
address recipient,
uint256 senderCommitmentId,
CommitmentDetails memory recipientCommitment,
PointEC memory excessCommitment,
PointEC memory senderPubKey,
PointEC memory recipientPubKey,
PointEC memory excessPubKey,
SlotSchnorrSignature memory schnorrSignatureSet
) public {
require(
SchnorrSignatureVerify(
schnorrSignatureSet.message,
schnorrSignatureSet.publicKey,
schnorrSignatureSet.ecR,
schnorrSignatureSet.s
),
"invalid signature"
);
CommitmentDetails memory senderCommitment = _commitmentById[msg.sender][
senderCommitmentId
];
require(senderCommitment.asset == recipientCommitment.asset, "Different assets");
require(!_spents[msg.sender][senderCommitmentId], "Commitment already used");
PointEC memory _ecVerify;
PointEC memory _ecSum;
(_ecVerify.x, _ecVerify.y) = eAdd(
recipientPubKey.x,
recipientPubKey.y,
excessPubKey.x,
excessPubKey.y
);
(_ecVerify.x, _ecVerify.y) = eSub(
senderPubKey.x,
senderPubKey.y,
_ecVerify.x,
_ecVerify.y
);
(_ecSum.x, _ecSum.y) = eAdd(
recipientCommitment.commitment.x,
recipientCommitment.commitment.y,
excessCommitment.x,
excessCommitment.y
);
require(
_CommitmentVerify(senderCommitment.commitment, _ecSum, _ecVerify),
"invalid commitments"
);
_spents[msg.sender][senderCommitmentId] = true;
uint256 _id = _CommitmentNewAdd(
recipient,
recipientCommitment.commitment,
recipientCommitment.asset
);
emit CommitmentTransferred(
msg.sender,
recipient,
senderCommitmentId,
_id,
senderCommitment.commitment,
recipientCommitment.commitment
);
_id = _CommitmentNewAdd(msg.sender, excessCommitment, recipientCommitment.asset);
emit Excessed(msg.sender, _id, excessCommitment);
}
/**
* @dev Deposit xft tokens and save commitment to user.
* @param amountIn amount of xft to be swapped.
* @param amountComm amount of zkAsset to be deposited.
* @param recipientCommitment new commitment that will be saved for user:
commitment - new commitment
asset - asset of commitment.
* @param schnorrSignatureSet Set of Schnorr params:
* message - Signed message
* pubKey - Public key with which message was signed
* ecR - Signature part R
* s - Signature part s.
*/
function deposit(
uint256 amountIn,
uint256 amountComm,
CommitmentDetails memory recipientCommitment,
SlotSchnorrSignature memory schnorrSignatureSet
) public {
require(amountIn != 0 && amountComm != 0, "Amount cannot be 0");
(uint256 currPrice, ) = priceConsumer.exchangeAssets(
uint8(recipientCommitment.asset),
uint8(Assets.XFT),
amountComm
);
require(amountIn == currPrice, "Incorrect input amount");
require(
SchnorrSignatureVerify(
schnorrSignatureSet.message,
schnorrSignatureSet.publicKey,
schnorrSignatureSet.ecR,
schnorrSignatureSet.s
),
"invalid signature"
);
PointEC memory ecH = _genPointEC(abi.encodePacked(gx, gy));
(uint256 x, uint256 y) = ePedersenCommitmentPK(
amountComm,
schnorrSignatureSet.publicKey.x,
schnorrSignatureSet.publicKey.y,
ecH.x,
ecH.y
);
require(
x == recipientCommitment.commitment.x && y == recipientCommitment.commitment.y,
"this amount cannot be deposited"
);
IERC20(xftTokenAddress).safeTransferFrom(msg.sender, address(this), amountIn);
xftTokenAddress.burn(amountIn);
uint256 id = _CommitmentNewAdd(
msg.sender,
recipientCommitment.commitment,
recipientCommitment.asset
);
emit Deposited(msg.sender, amountIn, id, _commitmentById[msg.sender][id].commitment);
}
/**
* @dev Withdraw xft tokens.
* @param amount of xft to be withdrawn.
* @param recipientCommitmentOldId id of the withdrawn commitment.
* @param schnorrSignatureSet Set of Schnorr params:
* message - Signed message
* pubKey - Public key with which message was signed
* ecR - Signature part R
* s - Signature part s.
*/
function withdraw(
uint256 amount,
uint256 recipientCommitmentOldId,
SlotSchnorrSignature memory schnorrSignatureSet
) public {
require(
SchnorrSignatureVerify(
schnorrSignatureSet.message,
schnorrSignatureSet.publicKey,
schnorrSignatureSet.ecR,
schnorrSignatureSet.s
),
"invalid signature"
);
require(!_spents[msg.sender][recipientCommitmentOldId], "commitment already used");
PointEC memory ecH = _genPointEC(abi.encodePacked(gx, gy));
PointEC memory userCommitment = _commitmentById[msg.sender][recipientCommitmentOldId]
.commitment;
(uint256 x, uint256 y) = ePedersenCommitmentPK(
amount,
schnorrSignatureSet.publicKey.x,
schnorrSignatureSet.publicKey.y,
ecH.x,
ecH.y
);
require(x == userCommitment.x && y == userCommitment.y, "this amount cannot be withdrawn");
(uint256 xftAmount, ) = priceConsumer.exchangeAssets(
uint8(_commitmentById[msg.sender][recipientCommitmentOldId].asset),
uint8(Assets.XFT),
amount
);
xftTokenAddress.mint(msg.sender, xftAmount);
_spents[msg.sender][recipientCommitmentOldId] = true;
emit Withdrawn(msg.sender, amount, recipientCommitmentOldId, userCommitment);
}
/**
* @dev Group commitments with same assets, create new groupped commitment.
* @param _commIds Commitment ids that must be closed.
* @param _asset Commitmen asset.
* @param _ecNewCommitment New commitment.
* @param _pkSum Elliptic curve point for verification new commitment.
Subtracting grouped commitment and new must be equal to this point
(_pkSum = subtraction sum of public keys used for already existen commitments and public key used for new commitment)
*/
function groupCommitment(
uint256[] memory _commIds,
Assets _asset,
PointEC memory _ecNewCommitment,
PointEC memory _pkSum
) public {
PointEC memory grouped = _commitmentById[msg.sender][_commIds[0]].commitment;
for (uint256 i = 1; i < _commIds.length; i++) {
require(
_commitmentById[msg.sender][_commIds[i - 1]].asset ==
_commitmentById[msg.sender][_commIds[i]].asset,
"Commitments with different assets"
);
(grouped.x, grouped.y) = eAdd(
grouped.x,
grouped.y,
_commitmentById[msg.sender][_commIds[i]].commitment.x,
_commitmentById[msg.sender][_commIds[i]].commitment.y
);
}
require(_CommitmentVerify(grouped, _ecNewCommitment, _pkSum), "invalid commitment");
for (uint256 i = 0; i < _commIds.length; i++) {
_spents[msg.sender][_commIds[i]] = true;
}
uint256 id = _CommitmentNewAdd(msg.sender, _ecNewCommitment, _asset);
emit Grouped(msg.sender, id, _ecNewCommitment);
}
/**
* @dev Save commitment to user with id.
* @param _newOwner Address of user.
* @param _commitment Commitment.
* @param _asset Commitmen asset.
*/
function _CommitmentNewAdd(
address _newOwner,
PointEC memory _commitment,
Assets _asset
) internal returns (uint256) {
uint256 _id = _idsByAddress[_newOwner].length + 1;
_commitmentById[_newOwner][_id].commitment = _commitment;
_commitmentById[_newOwner][_id].asset = _asset;
_idsByAddress[_newOwner].push(_id);
_spents[_newOwner][_id] = false;
return _id;
}
/**
* @dev Function for verify 2 commitments. Subtracting two points must be equal to the third point.
* @param _ecCommInput First point.
* @param _ecCommOutput Second point.
* @param _ecCommValid Point of equality with the result of subtraction 2 points.
*/
function _CommitmentVerify(
PointEC memory _ecCommInput,
PointEC memory _ecCommOutput,
PointEC memory _ecCommValid
) internal pure returns (bool) {
PointEC memory _ecP;
(_ecP.x, _ecP.y) = eSub(_ecCommInput.x, _ecCommInput.y, _ecCommOutput.x, _ecCommOutput.y);
return _equalPointEC(_ecP, _ecCommValid);
}
}
// SPDX-License-Identifier: MIT
pragma solidity =0.8.4;
import "./EllipticCurveMath.sol";
contract EllipticCurve {
// y^2 = x^3 + a*x + b (mod p) - elliptic curve
// aa, bb, (gx, gy), pp, nn - recommended parameters for elliptic curve secp256k1
uint256 public constant pp =
uint256(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F); // prime number p, constraint for y^2
uint256 public constant nn =
uint256(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141); // prime number n, constraint for x
// gx, gy - base point G coordinates
uint256 public constant gx =
uint256(0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798);
uint256 public constant gy =
uint256(0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8);
uint256 public constant aa =
uint256(0x0000000000000000000000000000000000000000000000000000000000000000);
uint256 public constant bb =
uint256(0x0000000000000000000000000000000000000000000000000000000000000007);
/**
* @dev eAdd returns the sum of (x1,y1) and (x2,y2) elliptic curve points coordinates.
* @param _x1 X coordinate of first point.
* @param _y1 Y coordinate of first point.
* @param _x2 X coordinate of second point.
* @param _y2 Y coordinate of second point.
* @return _x3 _y3 point coordinates.
*/
function eAdd(
uint256 _x1,
uint256 _y1,
uint256 _x2,
uint256 _y2
) public pure returns (uint256 _x3, uint256 _y3) {
(_x3, _y3) = EllipticCurveMath._ecAdd(_x1, _y1, _x2, _y2, 0, pp);
}
/**
* @dev eSub substract two points (x1, y1) and (x2, y2).
* @param _x1 X coordinate of first point.
* @param _y1 Y coordinate of first point.
* @param _x2 X coordinate of second point.
* @param _y2 Y coordinate of second point.
* @return _x3 _y3 point coordinates.
*/
function eSub(
uint256 _x1,
uint256 _y1,
uint256 _x2,
uint256 _y2
) public pure returns (uint256 _x3, uint256 _y3) {
(_x3, _y3) = EllipticCurveMath._ecSub(_x1, _y1, _x2, _y2, 0, pp);
}
/**
* @dev Multiplies point by scalar and returns the resulting point.
* @param _z scalar.
* @param _x1 X coordinate of point.
* @param _y1 Y coordinate of point.
* @return _x2 _y2 point coordinates.
*/
function eMul(
uint256 _z,
uint256 _x1,
uint256 _y1
) public pure returns (uint256 _x2, uint256 _y2) {
(_x2, _y2) = EllipticCurveMath._ecMul(_z, _x1, _y1, 0, pp);
}
/**
* @dev Returns EC point coordinate y with known x
* @param _prefix parity byte (0x02 even, 0x03 odd).
* @param _x coordinate x.
* @return _y coordinate y.
*/
function eDeriveY(uint8 _prefix, uint256 _x) public pure returns (uint256 _y) {
_y = EllipticCurveMath._deriveY(_prefix, _x, aa, bb, pp);
}
/**
* @dev Check is point on curve and return true if (x,y) in the curve, else - false
* @param _x X coordinate of point.
* @param _y Y coordinate of point.
* @return _is result of check.
*/
function eIsOnCurve(uint256 _x, uint256 _y) public pure returns (bool _is) {
_is = EllipticCurveMath._isOnCurve(_x, _y, aa, bb, pp);
}
/**
* @dev Modular euclidean inverse of a number (mod p).
* @param _x value.
* @param _pp mod.
* @return _g inversed value.
*/
function invMod(uint256 _x, uint256 _pp) public pure returns (uint256 _g) {
_g = EllipticCurveMath._invMod(_x, _pp);
}
// Modular exponentiation, returns '_base' raised to the power of '_exp' modulo '_pp'
function expMod(
uint256 _base,
uint256 _exp,
uint256 _pp
) public pure returns (uint256 _r) {
_r = EllipticCurveMath._expMod(_base, _exp, _pp);
}
/**
* @dev Generates the point of an elliptic curve inverted to (_x1, _y1)
* @param _x1 Secret value x.
* @param _y1 Blinding factor to x - r.
* @return _x2 _y2 point coordinates.
*/
function eInv(uint256 _x1, uint256 _y1) public pure returns (uint256 _x2, uint256 _y2) {
(_x2, _y2) = EllipticCurveMath._ecInv(_x1, _y1, pp);
}
/**
* @dev Generates Pederson Commitment with no fixed points x*G + r*H
* @param _x Secret value x.
* @param _r Blinding factor to x - r.
* @param _gx X coordinate of point G.
* @param _gy Y coordinate of point G.
* @param _hx X coordinate of point H.
* @param _hy Y coordinate of point H.
* @return _x3 _y3 point coordinates.
*/
function ePedersenCommitment(
uint256 _x,
uint256 _r,
uint256 _gx,
uint256 _gy,
uint256 _hx,
uint256 _hy
) public pure returns (uint256 _x3, uint256 _y3) {
// x*G
(uint256 _x1, uint256 _y1) = eMul(_x, _gx, _gy);
// r*H
(uint256 _x2, uint256 _y2) = eMul(_r, _hx, _hy);
// x*G+r*H
(_x3, _y3) = eAdd(_x1, _y1, _x2, _y2);
}
/**
* @dev Generates Pederson Commitment with no fixed points x*G + r*H, when x*G is already calculated.
* @param _r Blinding factor to x - r.
* @param _pkx X coordinate of calculated left part(x*G).
* @param _pky Y coordinate of calculated left part(x*G).
* @param _hx X coordinate of point H.
* @param _hy Y coordinate of point H.
* @return _x3 _y3 point coordinates.
*/
function ePedersenCommitmentPK(
uint256 _r,
uint256 _pkx,
uint256 _pky,
uint256 _hx,
uint256 _hy
) public pure returns (uint256 _x3, uint256 _y3) {
// _r*H
(uint256 _x2, uint256 _y2) = eMul(_r, _hx, _hy);
// _pkx - (x*H)
// _pkx + _r*H
(_x3, _y3) = eAdd(_pkx, _pky, _x2, _y2);
}
}
// SPDX-License-Identifier: MIT
pragma solidity =0.8.4;
//Elliptic Curve Library
//Library providing arithmetic operations over elliptic curves.
//This library does not check whether the inserted points belong to the curve
//`isOnCurve` function should be used by the library user to check the aforementioned statement.
//@author Witnet Foundation
library EllipticCurveMath {
// Pre-computed constant for 2 ** 255
uint256 private constant _U255_MAX_PLUS_1 =
57896044618658097711785492504343953926634992332820282019728792003956564819968;
// Modular euclidean inverse of a number (mod p).
// q such that x*q = 1 (mod _pp)
function _invMod(uint256 _x, uint256 _pp) internal pure returns (uint256) {
require(_x != 0 && _x != _pp && _pp != 0, "Invalid number");
uint256 q = 0;
uint256 newT = 1;
uint256 r = _pp;
uint256 t;
while (_x != 0) {
t = r / _x;
(q, newT) = (newT, addmod(q, (_pp - mulmod(t, newT, _pp)), _pp));
(r, _x) = (_x, r - t * _x);
}
return q;
}
/// Modular exponentiation, b^e % _pp.
/// Source: https://github.com/androlo/standard-contracts/blob/master/contracts/src/crypto/ECCMath.sol
/// r such that r = b**e (mod _pp)
function _expMod(
uint256 _base,
uint256 _exp,
uint256 _pp
) internal pure returns (uint256) {
require(_pp != 0, "Modulus is zero");
if (_base == 0) return 0;
if (_exp == 0) return 1;
uint256 r = 1;