编译器
0.8.17+commit.8df45f5f
文件 1 的 45:AccessControl.sol
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}
文件 2 的 45:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 3 的 45:AxelarInfo.sol
pragma solidity ^0.8.6;
struct AxelarChainInfo{
string destinationChain;
string destinationAddress;
uint256 messageFee;
}
struct AxelarCapsule{
AxelarChainInfo[] chains;
uint256 totalMessageFees;
}
文件 4 的 45:CircomData.sol
pragma solidity ^0.8.6;
import "./StealthAddressStructure.sol";
uint256 constant CIRCOM_P = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
struct CircomData {
uint256 rootHashHinkal;
address[] erc20TokenAddresses;
uint256[] tokenIds;
int256[] amountChanges;
uint256[][] inputNullifiers;
uint256[][] outCommitments;
bytes[][] encryptedOutputs;
uint256[] flatFees;
uint256 timeStamp;
StealthAddressStructure stealthAddressStructure;
uint256 rootHashAccessToken;
uint256 calldataHash;
uint16 publicSignalCount;
address relay;
address externalAddress;
uint256 externalActionId;
bytes externalActionMetadata;
HookData hookData;
}
struct HookData {
address preHookContract;
address hookContract;
bytes preHookMetadata;
bytes postHookMetadata;
}
文件 5 的 45:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 6 的 45:Dimensions.sol
pragma solidity ^0.8.6;
struct Dimensions {
uint16 tokenNumber;
uint16 nullifierAmount;
uint16 outputAmount;
}
文件 7 的 45:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 8 的 45:Hinkal.sol
pragma solidity ^0.8.17;
import "./HinkalBase.sol";
import "./VerifierFacade.sol";
import "./types/IHinkal.sol";
import "./types/IExternalAction.sol";
import "./types/ITransactHook.sol";
contract Hinkal is IHinkal, VerifierFacade, HinkalBase {
mapping(uint256 => address) internal externalActionMap;
constructor(
IMerkle.MerkleConstructorArgs memory constructorArgs,
address _hinkalHelper,
address _accessToken,
address _hinkalHelperManager
)
HinkalBase(
constructorArgs,
_hinkalHelper,
_accessToken,
_hinkalHelperManager
)
{}
function registerExternalAction(
uint256 externalActionId,
address externalActionAddress
) public onlyRole(DEFAULT_ADMIN_ROLE) {
externalActionMap[externalActionId] = externalActionAddress;
emit ExternalActionRegistered(externalActionAddress);
}
function removeExternalAction(
uint256 externalActionId
) public onlyRole(DEFAULT_ADMIN_ROLE) {
address externalActionAddress = externalActionMap[externalActionId];
delete externalActionMap[externalActionId];
emit ExternalActionRemoved(externalActionAddress);
}
function transact(
uint256[2] calldata a,
uint256[2][2] calldata b,
uint256[2] calldata c,
Dimensions calldata dimensions,
CircomData calldata circomData
) public payable nonReentrant {
_transact(a, b, c, dimensions, circomData);
}
function transactWithExternalAction(
uint256[2] calldata a,
uint256[2][2] calldata b,
uint256[2] calldata c,
Dimensions calldata dimensions,
CircomData calldata circomData
) public payable nonReentrant {
require(circomData.externalActionId != 0, "externalAddress is missing");
_transact(a, b, c, dimensions, circomData);
}
function transactWithHook(
uint256[2] calldata a,
uint256[2][2] calldata b,
uint256[2] calldata c,
Dimensions calldata dimensions,
CircomData calldata circomData
) public payable nonReentrant {
require(
circomData.hookData.hookContract != address(0) ||
circomData.hookData.preHookContract != address(0),
"hookContract is missing"
);
_transact(a, b, c, dimensions, circomData);
}
function transactWithExternalActionAndHook(
uint256[2] calldata a,
uint256[2][2] calldata b,
uint256[2] calldata c,
Dimensions calldata dimensions,
CircomData calldata circomData
) public payable nonReentrant {
require(circomData.externalActionId != 0, "externalAddress is missing");
require(
circomData.hookData.hookContract != address(0) ||
circomData.hookData.preHookContract != address(0),
"hookContract is missing"
);
_transact(a, b, c, dimensions, circomData);
}
function _transact(
uint256[2] calldata a,
uint256[2][2] calldata b,
uint256[2] calldata c,
Dimensions calldata dimensions,
CircomData calldata circomData
) internal {
{
uint256[] memory inputForCircom = hinkalHelper.performHinkalChecks(
circomData,
dimensions
);
require(
verifyProof(
a,
b,
c,
inputForCircom,
buildVerifierId(dimensions, circomData.externalActionId)
),
"Invalid Proof"
);
require(
rootHashExists(circomData.rootHashHinkal),
"Hinkal Root Hash is Incorrect"
);
require(
accessToken.checkForRootHash(
circomData.rootHashAccessToken,
msg.sender
),
"Access Token Root Hash is Incorrect"
);
require(
circomData.timeStamp > block.timestamp - 7 * 60 &&
circomData.timeStamp < block.timestamp + 7 * 60,
"Timestamp provided does not align with current time"
);
}
{
UTXO[] memory utxoSet;
if (circomData.hookData.preHookContract != address(0)) {
IPreTransactHook transactHook = IPreTransactHook(
circomData.hookData.preHookContract
);
transactHook.preTransact(
circomData,
circomData.hookData.preHookMetadata
);
}
uint256[] memory oldBalances = getBalancesForArray(
circomData.erc20TokenAddresses,
circomData.tokenIds
);
if (circomData.externalActionId == 0) {
_internalTransact(circomData);
} else {
utxoSet = _internalRunExternalAction(circomData);
}
uint256[] memory newBalances = getBalancesForArray(
circomData.erc20TokenAddresses,
circomData.tokenIds
);
OnChainCommitment[]
memory onChainCommitments = new OnChainCommitment[](
utxoSet.length
);
uint256 onChainCommitmentCounter = 0;
for (uint64 i; i < circomData.erc20TokenAddresses.length; i++) {
int256 balanceDif;
if (circomData.erc20TokenAddresses[i] == address(0)) {
balanceDif =
int256(newBalances[i]) +
int256(msg.value) -
int256(oldBalances[i]);
} else {
balanceDif =
int256(newBalances[i]) -
int256(oldBalances[i]);
}
require(
balanceDif >= circomData.amountChanges[i],
"Inbalance in token detected"
);
uint256 utxoAmount = 0;
for (uint j = 0; j < utxoSet.length; j++) {
if (
utxoSet[j].erc20Address ==
circomData.erc20TokenAddresses[i]
) {
utxoAmount = utxoSet[j].amount;
onChainCommitments[
onChainCommitmentCounter++
] = createCommitment(utxoSet[j]);
break;
}
}
require(
balanceDif ==
int256(utxoAmount) +
int256(identity(circomData.outCommitments[i][0])) *
circomData.amountChanges[i],
"Balance Diff Should be equal to sum of onchain and offchain created commitments"
);
}
if (circomData.hookData.hookContract != address(0)) {
ITransactHook transactHook = ITransactHook(
circomData.hookData.hookContract
);
transactHook.afterTransact(
circomData,
circomData.hookData.postHookMetadata
);
}
insertNullifiers(circomData.inputNullifiers);
insertCommitments(
circomData.outCommitments,
circomData.encryptedOutputs,
onChainCommitments
);
}
}
function _internalTransact(CircomData calldata circomData) private {
for (uint64 i = 0; i < circomData.erc20TokenAddresses.length; i++) {
if (circomData.amountChanges[i] > 0) {
require(
circomData.externalAddress == msg.sender,
"Deposit should come from the sender"
);
transferTokenFrom(
circomData.erc20TokenAddresses[i],
circomData.externalAddress,
address(this),
uint256(circomData.amountChanges[i]),
circomData.tokenIds[i]
);
} else if (circomData.amountChanges[i] < 0) {
uint256 relayFee = 0;
if (circomData.relay != address(0)) {
relayFee = hinkalHelper.calculateRelayFee(
uint256(-circomData.amountChanges[i]),
circomData.erc20TokenAddresses[i],
circomData.flatFees[i],
circomData.externalActionId
);
require(
relayFee <= uint256(-circomData.amountChanges[i]),
"Relay Fee is over withdraw amount"
);
if (circomData.tokenIds[i] == 0)
transferERC20TokenOrETH(
circomData.erc20TokenAddresses[i],
circomData.relay,
relayFee
);
}
transferToken(
circomData.erc20TokenAddresses[i],
circomData.externalAddress,
uint256(-circomData.amountChanges[i]) - relayFee,
circomData.tokenIds[i]
);
}
}
}
function _internalRunExternalAction(
CircomData calldata circomData
) internal returns (UTXO[] memory) {
require(
externalActionMap[circomData.externalActionId] ==
circomData.externalAddress &&
circomData.externalAddress != address(0),
"Unknown externalAddress"
);
for (uint64 i = 0; i < circomData.erc20TokenAddresses.length; i++) {
if (circomData.amountChanges[i] < 0) {
transferToken(
circomData.erc20TokenAddresses[i],
circomData.externalAddress,
uint256(-circomData.amountChanges[i]),
circomData.tokenIds[i]
);
}
}
return
IExternalAction(circomData.externalAddress).runAction(circomData);
}
}
文件 9 的 45:HinkalBase.sol
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "./types/IHinkalBase.sol";
import "./types/IHinkalHelper.sol";
import "./types/ICrossChainAccessToken.sol";
import "./types/IMerkle.sol";
import "./Merkle.sol";
import "./OwnerHinkal.sol";
import "./Transferer.sol";
import "./types/CircomData.sol";
contract HinkalBase is
IHinkalBase,
Merkle,
Transferer,
AccessControl,
ReentrancyGuard
{
mapping(uint256 => bool) public nullifiers;
IHinkalHelper public hinkalHelper;
ICrossChainAccessToken public accessToken;
bytes32 public constant HINKAL_HELPER_MANAGER =
keccak256("HINKAL_HELPER_MANAGER");
constructor(
IMerkle.MerkleConstructorArgs memory constructorArgs,
address _hinkalHelper,
address _accessToken,
address _hinkalHelperManager
) Merkle(constructorArgs) {
hinkalHelper = IHinkalHelper(_hinkalHelper);
accessToken = ICrossChainAccessToken(_accessToken);
_setRoleAdmin(HINKAL_HELPER_MANAGER, HINKAL_HELPER_MANAGER);
_grantRole(HINKAL_HELPER_MANAGER, _hinkalHelperManager);
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
receive() external payable {}
function setHinkalHelper(
address _hinkalHelper
) external onlyRole(HINKAL_HELPER_MANAGER) {
hinkalHelper = IHinkalHelper(_hinkalHelper);
}
function setAccessToken(
address _accessToken
) external onlyRole(HINKAL_HELPER_MANAGER) {
accessToken = ICrossChainAccessToken(_accessToken);
}
function register(bytes calldata shieldedAddressHash) external {
accessToken.registerCheck(msg.sender);
emit Register(msg.sender, shieldedAddressHash);
}
function createCommitment(
UTXO memory utxo
) internal view returns (OnChainCommitment memory) {
uint256 commitment;
if (utxo.tokenId > 0) {
commitment = hash5(
utxo.amount,
uint256(uint160(utxo.erc20Address)),
utxo.stealthAddressStructure.stealthAddress,
utxo.timeStamp,
utxo.tokenId
);
} else {
commitment = hash4(
utxo.amount,
uint256(uint160(utxo.erc20Address)),
utxo.stealthAddressStructure.stealthAddress,
utxo.timeStamp
);
}
OnChainCommitment memory onChainCommitment = OnChainCommitment({
utxo: utxo,
commitment: commitment
});
return onChainCommitment;
}
function insertCommitments(
uint256[][] calldata outCommitments,
bytes[][] calldata encryptedOutputs,
OnChainCommitment[] memory onChainCommitments
) internal {
uint256 length = 0;
for (uint16 i = 0; i < outCommitments.length; i++) {
for (uint16 j = 0; j < outCommitments[i].length; j++) {
length += identity(outCommitments[i][j]);
}
}
length += onChainCommitments.length;
if (length > 0) {
uint256[] memory leaves = new uint256[](length);
uint256 index = 0;
for (uint16 i = 0; i < outCommitments.length; i++) {
for (uint16 j = 0; j < outCommitments[i].length; j++) {
if (outCommitments[i][j] != 0)
leaves[index++] = outCommitments[i][j];
}
}
for (uint16 i = 0; i < onChainCommitments.length; i++) {
leaves[index++] = onChainCommitments[i].commitment;
}
uint256[] memory insertedIndexes = insertMany(leaves);
index = 0;
for (uint16 i = 0; i < encryptedOutputs.length; i++) {
for (uint16 j = 0; j < encryptedOutputs[i].length; j++) {
if (outCommitments[i][j] != 0) {
emit NewCommitment(
leaves[index],
int256(insertedIndexes[index]),
encryptedOutputs[i][j]
);
index++;
}
}
}
for (uint16 i = 0; i < onChainCommitments.length; i++) {
emit NewCommitment(
leaves[index],
-1 * int256(insertedIndexes[index++]),
abi.encode(onChainCommitments[i].utxo)
);
}
}
}
function insertNullifiers(uint256[][] calldata inputNullifiers) internal {
for (uint256 i = 0; i < inputNullifiers.length; i++) {
for (uint16 j = 0; j < inputNullifiers[i].length; j++) {
if (inputNullifiers[i][j] == 0) continue;
require(
!nullifiers[inputNullifiers[i][j]],
"Nullifier cannot be reused"
);
nullifiers[inputNullifiers[i][j]] = true;
emit Nullified(inputNullifiers[i][j]);
}
}
}
function identity(uint256 value) internal pure returns (uint256) {
return value > 0 ? 1 : 0;
}
}
文件 10 的 45:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 11 的 45:ICircomDataBuilder.sol
pragma solidity >=0.8.0;
import "./CircomData.sol";
interface ICircomDataBuilder {
function getHashedCalldata(
CircomData memory circomData
) external pure returns (uint256);
function formInputForCircom(
CircomData memory circomData
) external pure returns (uint256[] memory input);
}
文件 12 的 45:ICrossChainAccessToken.sol
pragma solidity >=0.8.0;
import "./IMerkle.sol";
import "./AxelarInfo.sol";
struct SignatureData {
uint8 v;
bytes32 r;
bytes32 s;
uint256 accessKey;
uint256 nonce;
}
struct AccessTokenWithAddress {
uint256 accessToken;
address ethAddress;
}
interface ICrossChainAccessToken is IMerkle {
event NewAccessKeyAdded(
uint256 accessKey,
uint256 index,
address senderAddress
);
event MintingFeeChanged(uint256 newMintingFee);
event AccessKeyBlacklisted(uint256 blacklistedAccessKey);
event AddressBlacklisted(address blacklistedAddress);
event AddressRemovedFromBlacklist(address addressToRestore);
event FundsWithdrawnFromAccessToken(uint256 amount);
event AccessKeyMigrationReceived(uint256 accessKey, string sourceChain);
event CrossChainAccessTokenRegistryChange(
string sourceChain,
address sourceAddress
);
struct CrossChainAccessTokenRegistryUpdate {
string sourceChain;
address sourceAddress;
}
function usedNonces(uint256) external view returns (bool);
function addToken(SignatureData calldata signatureData) external payable;
function blacklistAddresses(address) external view returns (bool);
function setMintingFee(uint256 _mintingFee) external;
function hasToken(uint256 accessKey) external view returns (bool);
function blacklistAccessKey(uint256 accessKey, uint256 index) external;
function blacklistAddress(address _address) external;
function removeAddressFromBlacklist(address addressToRestore) external;
function withdraw() external;
function setAxelarGasService(address _gasService) external;
function addTokenCrossChain(
SignatureData calldata signatureData,
AxelarCapsule calldata capsule
) external payable;
function migrateAccessToken(
AxelarCapsule calldata capsule,
uint256 accessKey
) external payable;
function registerCheck(address sender) external view;
function checkForRootHash(
uint256 rootHashAccessToken,
address sender
) external view returns (bool);
}
文件 13 的 45:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 14 的 45:IERC20.sol
pragma solidity ^0.8.0;
import "../token/ERC20/IERC20.sol";
文件 15 的 45:IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 16 的 45:IERC20TokenRegistry.sol
pragma solidity ^0.8.17;
interface IERC20TokenRegistry {
event RegistryStateChanged(bool isEnabled);
event TokenAdded(address erc20Token);
event TokenRemoved(address erc20Token);
event TokenLimit(address erc20Token, uint256 tokenLimit);
function tokenRegistry(address) external returns (bool);
function tokenLimits(address) external returns (uint256);
function enabled() external view returns (bool);
function changeState(bool _enabled) external;
function addERCToken(address erc20Token) external;
function removeToken(address erc20Token) external;
function tokenInRegistry(address erc20Token) external view returns (bool);
function setTokenLimit(address _token, uint256 _tokenLimit) external;
function getTokenLimit(address _token) external view returns (uint256);
}
文件 17 的 45:IERC721.sol
pragma solidity ^0.8.0;
import "../token/ERC721/IERC721.sol";
文件 18 的 45:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 19 的 45:IExternalAction.sol
pragma solidity ^0.8.6;
import "./CircomData.sol";
import "./UTXO.sol";
interface IExternalAction {
function runAction(
CircomData calldata circomData
) external returns (UTXO[] memory);
}
文件 20 的 45:IHinkal.sol
pragma solidity ^0.8.6;
import "../types/Dimensions.sol";
import "../types/CircomData.sol";
interface IHinkal {
event ExternalActionRegistered(address externalActionAddress);
event ExternalActionRemoved(address externalActionAddress);
struct ConstructorArgs {
uint256 levels;
address poseidon;
address accessTokenAddress;
address circomDataBuilderAddress;
address erc20TokenRegistryAddress;
address relayStoreAddress;
}
function transact(
uint256[2] calldata a,
uint256[2][2] calldata b,
uint256[2] calldata c,
Dimensions calldata dimensions,
CircomData calldata circomData
) external payable;
function transactWithExternalAction(
uint256[2] calldata a,
uint256[2][2] calldata b,
uint256[2] calldata c,
Dimensions calldata dimensions,
CircomData calldata circomData
) external payable;
function transactWithHook(
uint256[2] calldata a,
uint256[2][2] calldata b,
uint256[2] calldata c,
Dimensions calldata dimensions,
CircomData calldata circomData
) external payable;
function transactWithExternalActionAndHook(
uint256[2] calldata a,
uint256[2][2] calldata b,
uint256[2] calldata c,
Dimensions calldata dimensions,
CircomData calldata circomData
) external payable;
}
文件 21 的 45:IHinkalBase.sol
pragma solidity ^0.8.17;
import "./IRelayStore.sol";
import "./UTXO.sol";
interface IHinkalBase {
event Register(address ethereumAddress, bytes shieldedAddressHash);
event NewCommitment(
uint256 commitment,
int256 index,
bytes encryptedOutput
);
event Nullified(uint256 nullifier);
event NewTransaction(
address sender,
uint256 timestamp,
address erc20TokenAddress,
int256 publicAmount
);
event NewUtxo(
uint256 amount,
address erc20Address,
uint256 randomization,
uint256 stealthAddress,
uint256 timeStamp,
uint256 tokenId
);
function setHinkalHelper(address _hinkalHelper) external;
}
文件 22 的 45:IHinkalHelper.sol
pragma solidity ^0.8.17;
import "./IRelayStore.sol";
import "./ICircomDataBuilder.sol";
import "./Dimensions.sol";
import "./IRelayStore.sol";
import "./IERC20TokenRegistry.sol";
interface IHinkalHelper is IRelayStore, IERC20TokenRegistry {
function getRelayStore() external view returns (RelayEntry[] memory);
function relayerIsValid(address relay) external view;
function checkTokenRegistry(
address[] calldata erc20TokenAddresses,
int256[] calldata amountChanges
) external view;
function performHinkalChecks(
CircomData calldata circomData,
Dimensions calldata dimensions
) external view returns (uint256[] memory);
}
文件 23 的 45:IMerkle.sol
pragma solidity ^0.8.17;
interface IMerkle {
struct MerkleConstructorArgs {
uint128 levels;
address poseidon2;
address poseidon4;
address poseidon5;
}
function hash2(uint256 a, uint256 b) external view returns (uint256);
function getRootHash() external view returns (uint256);
function rootHashExists(uint256 _root) external view returns (bool);
function logarithm2(uint256 x) external pure returns (uint256);
}
文件 24 的 45:IPoseidon2.sol
pragma solidity >=0.8.0;
interface IPoseidon2 {
function poseidon(uint256[2] memory input) external pure returns (uint256);
function poseidon(bytes32[2] memory input) external pure returns (bytes32);
}
文件 25 的 45:IPoseidon4.sol
pragma solidity >=0.8.0;
interface IPoseidon4 {
function poseidon(uint256[4] memory input) external pure returns (uint256);
function poseidon(bytes32[4] memory input) external pure returns (bytes32);
}
文件 26 的 45:IPoseidon5.sol
pragma solidity >=0.8.0;
interface IPoseidon5 {
function poseidon(uint256[5] memory input) external pure returns (uint256);
function poseidon(bytes32[5] memory input) external pure returns (bytes32);
}
文件 27 的 45:IRelayStore.sol
pragma solidity ^0.8.17;
struct RelayEntry {
address relayAddress;
string url;
uint256 priority;
}
interface IRelayStore {
event RelayPercentageChanged(uint32 newRelayPercentage);
event RelayPercentageExternalChanged(uint32 newRelayPercentage);
event RelayAddedOrSet(address relayAddress, string url, uint256 priority);
event RelayRemoved(address relayAddress);
function getRelayPercentage(
uint256 amount,
address erc20Address
) external view returns (uint32);
function setRelayPercentage(uint32 _relayPercentage) external;
function getRelayPercentageExternal(
uint256 amount,
address erc20Address,
uint256 externalActionId
) external view returns (uint32);
function setRelayPercentageExternal(
uint32 _relayPercentageExternal
) external;
function isRelayInList(address relay) external view returns (bool);
function getRelayStore() external view returns (RelayEntry[] memory);
function removeRelay(address _relayAddress) external;
function addOrSetRelay(
address relayAddress,
string memory url,
uint256 priority
) external;
function calculateRelayFee(
uint256 balance,
address tokenAddress,
uint256 flatFee,
uint256 externalActionId
) external view returns (uint256 relayFee);
}
文件 28 的 45:ITransactHook.sol
pragma solidity ^0.8.6;
import "./CircomData.sol";
interface IPreTransactHook {
function preTransact(
CircomData calldata circomData,
bytes calldata metadata
) external;
}
interface ITransactHook {
function afterTransact(
CircomData calldata circomData,
bytes calldata metadata
) external;
}
文件 29 的 45:IVerifier.sol
pragma solidity ^0.8.6;
interface IVerifier {
function verifyProof(
uint256[2] memory a,
uint256[2][2] memory b,
uint256[2] memory c,
uint256[] memory input,
uint256 verifierId
) view external returns (bool);
}
文件 30 的 45:IVerifierFacade.sol
pragma solidity ^0.8.17;
import "./IVerifier.sol";
import "./Dimensions.sol";
interface IVerifierFacade {
event VerifierRegistered(uint256 verifierId, address verifierAddress);
event VerifierRemoved(uint256 verifierId);
function registerVerifiers(
uint256[] calldata verifierIds,
address[] calldata verifierAddresses
) external;
function removeVerifier(uint256 verifierId) external;
function buildVerifierId(
Dimensions calldata dimensions,
uint256 externalActionId
) external pure returns (uint256);
}
文件 31 的 45:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1, "Math: mulDiv overflow");
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
文件 32 的 45:Merkle.sol
pragma solidity ^0.8.17;
import "./types/IPoseidon2.sol";
import "./MerkleBase.sol";
contract Merkle is MerkleBase {
constructor(
MerkleConstructorArgs memory constructorArgs
) MerkleBase(constructorArgs) {}
function outputGas(uint256 index, uint256[] memory gasUsed) internal view {
gasUsed[index] = gasleft();
}
function insert(uint256 leaf) internal override returns (uint256) {
uint256 newIndex = ++m_index;
uint256 currentNodeIndex = newIndex - 1;
require(m_index <= uint256(2) ** LEVELS, "Tree is full.");
uint256 fullCount = newIndex - MINIMUM_INDEX;
uint256 twoPower = logarithm2(fullCount);
uint256 prevHash = leaf;
insertOne(currentNodeIndex, twoPower, prevHash);
roots[rootIndex] = tree[twoPower];
rootIndex = (rootIndex + 1) % MAX_ROOT_NUMBER;
return newIndex - 1;
}
function insertMany(
uint256[] memory leaves
) internal returns (uint256[] memory insertedIndexes) {
m_index += uint128(leaves.length);
uint256 newIndex = m_index;
uint256 currentNodeIndex = newIndex - leaves.length;
require(m_index <= uint256(2) ** LEVELS, "Tree is full.");
insertedIndexes = new uint256[](leaves.length);
for (uint256 i = 0; i < insertedIndexes.length; i++) {
insertedIndexes[i] = currentNodeIndex + i;
}
uint256[][] memory sortedLeaves = sortInPairs(leaves, currentNodeIndex);
uint256 fullCount = newIndex - MINIMUM_INDEX;
uint256 twoPower = logarithm2(fullCount);
for (uint256 i = 0; i < sortedLeaves.length; i++) {
if (sortedLeaves[i].length == 1)
insertOne(currentNodeIndex++, twoPower, sortedLeaves[i][0]);
else {
insertTwo(
sortedLeaves[i][0],
sortedLeaves[i][1],
currentNodeIndex,
twoPower
);
currentNodeIndex += 2;
}
}
roots[rootIndex] = tree[twoPower];
rootIndex = (rootIndex + 1) % MAX_ROOT_NUMBER;
}
function insertOne(
uint256 currentNodeIndex,
uint256 twoPower,
uint256 prevHash
) internal {
for (uint256 i = 0; i <= twoPower; i++) {
if (currentNodeIndex % 2 == 0 || currentNodeIndex == 1) {
tree[i] = prevHash;
if (i != twoPower) prevHash = hash2(prevHash, 0);
} else {
prevHash = hash2(tree[i], prevHash);
}
currentNodeIndex /= 2;
}
}
function insertTwo(
uint256 left,
uint256 right,
uint256 currentNodeIndex,
uint256 twoPower
) internal {
uint256 prevHash = hash2(left, right);
currentNodeIndex /= 2;
for (uint256 i = 1; i <= twoPower; i++) {
if (currentNodeIndex % 2 == 0 || currentNodeIndex == 1) {
tree[i] = prevHash;
if (i != twoPower) prevHash = hash2(prevHash, 0);
} else {
prevHash = hash2(tree[i], prevHash);
}
currentNodeIndex /= 2;
}
}
function sortInPairs(
uint256[] memory leaves,
uint256 currentNodeIndex
) internal pure returns (uint256[][] memory sortedLeaves) {
uint leavesLength = leaves.length;
bool firstLeafIfRight = currentNodeIndex % 2 != 0;
uint256 firstElement = firstLeafIfRight ? 1 : 0;
uint256 netElements = leavesLength - firstElement;
uint256 lengthWithoutFirst = (netElements % 2 == 0)
? netElements / 2
: (netElements + 1) / 2;
sortedLeaves = new uint256[][](firstElement + lengthWithoutFirst);
if (firstLeafIfRight) {
uint256[] memory first = new uint256[](1);
first[0] = leaves[0];
sortedLeaves[0] = first;
}
uint arrIndex = firstLeafIfRight ? 1 : 0;
uint sortedArrayIndex = arrIndex;
while (arrIndex < leavesLength) {
uint256[] memory arr;
if (arrIndex + 1 < leavesLength) {
arr = new uint256[](2);
arr[0] = leaves[arrIndex];
arr[1] = leaves[++arrIndex];
} else {
arr = new uint256[](1);
arr[0] = leaves[arrIndex];
}
sortedLeaves[sortedArrayIndex++] = arr;
++arrIndex;
}
}
}
文件 33 的 45:MerkleBase.sol
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/utils/math/Math.sol";
import "./types/IPoseidon2.sol";
import "./types/IPoseidon4.sol";
import "./types/IPoseidon5.sol";
import "./types/IMerkle.sol";
abstract contract MerkleBase is IMerkle {
using Math for uint256;
mapping(uint256 => uint256) public tree;
mapping(uint256 => uint256) roots;
uint128 public m_index;
uint128 public rootIndex = 0;
uint128 immutable LEVELS;
uint128 constant MAX_ROOT_NUMBER = 25;
uint256 immutable MINIMUM_INDEX;
IPoseidon2 public immutable poseidon2;
IPoseidon4 public immutable poseidon4;
IPoseidon5 public immutable poseidon5;
constructor(MerkleConstructorArgs memory constructorArgs) {
LEVELS = constructorArgs.levels;
m_index = uint128(2 ** (LEVELS - 1));
MINIMUM_INDEX = 2 ** (LEVELS - 1);
poseidon2 = IPoseidon2(constructorArgs.poseidon2);
poseidon4 = IPoseidon4(constructorArgs.poseidon4);
poseidon5 = IPoseidon5(constructorArgs.poseidon5);
}
function hash2(
uint256 a,
uint256 b
) public view returns (uint256 poseidonHash) {
poseidonHash = poseidon2.poseidon([a, b]);
}
function hash4(
uint256 a0,
uint256 a1,
uint256 a2,
uint256 a3
) public view returns (uint256 poseidonHash) {
poseidonHash = poseidon4.poseidon([a0, a1, a2, a3]);
}
function hash5(
uint256 a0,
uint256 a1,
uint256 a2,
uint256 a3,
uint256 a4
) public view returns (uint256 poseidonHash) {
poseidonHash = poseidon5.poseidon([a0, a1, a2, a3, a4]);
}
function insert(uint256 leaf) internal virtual returns (uint256);
function getRootHash() public view returns (uint256) {
return roots[rootIndex > 0 ? rootIndex - 1 : MAX_ROOT_NUMBER - 1];
}
function rootHashExists(uint256 _root) public view returns (bool) {
uint256 i = rootIndex;
do {
if (i == 0) {
i = MAX_ROOT_NUMBER;
}
i--;
if (_root == roots[i]) {
return true;
}
} while (i != rootIndex);
return false;
}
function logarithm2(uint256 x) public pure returns (uint256 y) {
y = Math.log2(x, Math.Rounding.Up);
}
}
文件 34 的 45:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 35 的 45:Ownable2Step.sol
pragma solidity ^0.8.0;
import "./Ownable.sol";
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
function acceptOwnership() public virtual {
address sender = _msgSender();
require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
_transferOwnership(sender);
}
}
文件 36 的 45:OwnerHinkal.sol
pragma solidity 0.8.17;
import "@openzeppelin/contracts/access/Ownable2Step.sol";
contract OwnerHinkal is Ownable2Step {
function renounceOwnership() public view override onlyOwner {
revert("The Ownership cannot be renounced");
}
}
文件 37 的 45:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
文件 38 的 45:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
文件 39 的 45:SignedMath.sol
pragma solidity ^0.8.0;
library SignedMath {
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
function average(int256 a, int256 b) internal pure returns (int256) {
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
function abs(int256 n) internal pure returns (uint256) {
unchecked {
return uint256(n >= 0 ? n : -n);
}
}
}
文件 40 的 45:StealthAddressStructure.sol
pragma solidity ^0.8.6;
struct StealthAddressStructure {
uint256 extraRandomization;
uint256 stealthAddress;
uint256 H0;
uint256 H1;
}
文件 41 的 45:Strings.sol
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
文件 42 的 45:Transferer.sol
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC721.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./TransfererBase.sol";
contract Transferer is TransfererBase {
using SafeERC20 for IERC20;
function onERC721Received(
address,
address,
uint256,
bytes calldata
) public pure returns (bytes4) {
return IERC721Receiver.onERC721Received.selector;
}
function unsafeApproveERC20Token(
address _erc20TokenAddress,
address _to,
uint256 _value
) internal {
IERC20(_erc20TokenAddress).approve(_to, 0);
IERC20(_erc20TokenAddress).approve(_to, _value);
}
function getERC20Allowance(
address _erc20TokenAddress,
address owner,
address spender
) internal view returns (uint256) {
IERC20 outToken = IERC20(_erc20TokenAddress);
return outToken.allowance(owner, spender);
}
function approveERC721Token(
address _erc20TokenAddress,
address _to,
uint256 _tokenId
) internal {
IERC721(_erc20TokenAddress).approve(_to, _tokenId);
}
function approveToken(
address _erc20TokenAddress,
address _to,
uint256 _tokenId,
uint256 _value
) internal {
if (_tokenId == 0) {
unsafeApproveERC20Token(_erc20TokenAddress, _to, _value);
} else {
approveERC721Token(_erc20TokenAddress, _to, _tokenId);
}
}
function transferETH(address _recepient, uint256 _value) internal {
(bool success, ) = _recepient.call{value: _value}("");
require(success, "Transfer Failed");
}
function transferERC20TokenFrom(
address _erc20TokenAddress,
address _from,
address _to,
uint256 _value
) internal {
IERC20(_erc20TokenAddress).safeTransferFrom(_from, _to, _value);
}
function transferNftFrom(
address _erc20TokenAddress,
address _from,
address _to,
uint256 _tokenId
) internal {
IERC721(_erc20TokenAddress).safeTransferFrom(_from, _to, _tokenId);
}
function transferERC20TokenOrETH(
address _erc20TokenAddress,
address _to,
uint256 _value
) internal {
if (_erc20TokenAddress == address(0)) {
transferETH(_to, _value);
} else {
transferERC20Token(_erc20TokenAddress, _to, _value);
}
}
function transferToken(
address _erc20TokenAddress,
address _to,
uint256 _value,
uint256 _tokenId
) internal {
if (_tokenId == 0) {
transferERC20TokenOrETH(_erc20TokenAddress, _to, _value);
} else {
transferNftFrom(_erc20TokenAddress, address(this), _to, _tokenId);
}
}
function multiTransfer(
address[] memory erc20TokenAddresses,
address _to,
uint256[] memory amounts
) internal returns (bool) {
for (uint64 i = 0; i < erc20TokenAddresses.length; i++) {
if (amounts[i] > 0)
transferERC20TokenOrETH(
erc20TokenAddresses[i],
_to,
amounts[i]
);
}
return true;
}
function transferERC20TokenFromOrCheckETH(
address _contractAddress,
address _from,
address _to,
uint256 _value
) internal {
if (_contractAddress == address(0)) {
require(
msg.value == _value,
"msg.value doesn't match needed amount"
);
if (_to != address(this)) {
transferETH(_to, _value);
}
} else {
transferERC20TokenFrom(_contractAddress, _from, _to, _value);
}
}
function transferTokenFrom(
address _erc20TokenAddress,
address _from,
address _to,
uint256 _value,
uint256 _tokenId
) internal {
if (_tokenId == 0) {
transferERC20TokenFromOrCheckETH(
_erc20TokenAddress,
_from,
_to,
_value
);
} else {
transferNftFrom(_erc20TokenAddress, _from, _to, _tokenId);
}
}
function multiTransferFrom(
address[] memory erc20TokenAddresses,
address _from,
address _to,
uint256[] memory amounts
) internal returns (bool) {
for (uint64 i = 0; i < erc20TokenAddresses.length; i++) {
if (amounts[i] > 0) {
transferERC20TokenFromOrCheckETH(
erc20TokenAddresses[i],
_from,
_to,
amounts[i]
);
}
}
return true;
}
function getERC20OrETHBalance(
address _erc20TokenAddress
) internal view returns (uint256) {
if (_erc20TokenAddress == address(0)) {
return address(this).balance;
} else {
IERC20 outToken = IERC20(_erc20TokenAddress);
return outToken.balanceOf(address(this));
}
}
function getNftBalance(
address _erc20TokenAddress,
uint256 tokenId
) internal view returns (uint256) {
IERC721 outToken = IERC721(_erc20TokenAddress);
try outToken.ownerOf(tokenId) returns (address owner) {
if (owner == address(this)) return 1;
else return 0;
} catch {
return 0;
}
}
function getBalancesForArrayMemory(
address[] memory erc20TokenAddresses
) internal view returns (uint256[] memory balances) {
balances = new uint256[](erc20TokenAddresses.length);
for (uint64 i; i < erc20TokenAddresses.length; i++) {
balances[i] = getERC20OrETHBalance(erc20TokenAddresses[i]);
}
}
function getBalancesForArrayMemory(
address[] memory erc20TokenAddresses,
uint256[] memory tokenIds
) internal view returns (uint256[] memory balances) {
balances = new uint256[](erc20TokenAddresses.length);
for (uint64 i; i < erc20TokenAddresses.length; i++) {
if (tokenIds[i] == 0) {
balances[i] = getERC20OrETHBalance(erc20TokenAddresses[i]);
} else {
balances[i] = getNftBalance(
erc20TokenAddresses[i],
tokenIds[i]
);
}
}
}
function getBalancesForArray(
address[] calldata erc20TokenAddresses
) internal view returns (uint256[] memory balances) {
balances = new uint256[](erc20TokenAddresses.length);
for (uint64 i; i < erc20TokenAddresses.length; i++) {
balances[i] = getERC20OrETHBalance(erc20TokenAddresses[i]);
}
}
function getBalancesForArray(
address[] calldata erc20TokenAddresses,
uint256[] calldata tokenIds
) internal view returns (uint256[] memory balances) {
balances = new uint256[](erc20TokenAddresses.length);
for (uint64 i; i < erc20TokenAddresses.length; i++) {
if (tokenIds[i] == 0) {
balances[i] = getERC20OrETHBalance(erc20TokenAddresses[i]);
} else {
balances[i] = getNftBalance(
erc20TokenAddresses[i],
tokenIds[i]
);
}
}
}
function sendToRelay(
address relay,
uint256 actualAmount,
address erc20TokenAddress
) internal {
if (relay != address(0) && actualAmount > 0) {
transferERC20TokenOrETH(
erc20TokenAddress,
relay,
uint256(actualAmount)
);
}
}
}
文件 43 的 45:TransfererBase.sol
pragma solidity ^0.8.17;
import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract TransfererBase {
using SafeERC20 for IERC20;
function transferERC20Token(
address _erc20TokenAddress,
address _to,
uint256 _value
) internal {
IERC20(_erc20TokenAddress).safeTransfer(_to, _value);
}
function approveERC20Token(
address _erc20TokenAddress,
address _to,
uint256 _value
) internal {
IERC20(_erc20TokenAddress).safeApprove(_to, 0);
IERC20(_erc20TokenAddress).safeApprove(_to, _value);
}
function approveUnlimited(
address _erc20TokenAddress,
address _to
) internal {
if (IERC20(_erc20TokenAddress).allowance(address(this), _to) < type(uint256).max / 2) {
IERC20(_erc20TokenAddress).safeApprove(_to, 0);
IERC20(_erc20TokenAddress).safeApprove(_to, type(uint256).max);
}
}
}
文件 44 的 45:UTXO.sol
pragma solidity >=0.8.0;
import "./StealthAddressStructure.sol";
struct UTXO {
uint256 amount;
address erc20Address;
StealthAddressStructure stealthAddressStructure;
uint256 timeStamp;
uint256 tokenId;
}
struct OnChainCommitment {
UTXO utxo;
uint256 commitment;
}
文件 45 的 45:VerifierFacade.sol
pragma solidity ^0.8.17;
import "./OwnerHinkal.sol";
import "./types/Dimensions.sol";
import "./types/IVerifierFacade.sol";
import "./types/IVerifier.sol";
contract VerifierFacade is IVerifierFacade, OwnerHinkal {
mapping(uint256 => IVerifier) internal verifierMap;
function registerVerifiers(
uint256[] calldata verifierIds,
address[] calldata verifierAddresses
) external onlyOwner {
for (uint i = 0; i < verifierIds.length; i++) {
verifierMap[verifierIds[i]] = IVerifier(verifierAddresses[i]);
emit VerifierRegistered(verifierIds[i], verifierAddresses[i]);
}
}
function removeVerifier(uint256 verifierId) external onlyOwner {
delete verifierMap[verifierId];
emit VerifierRemoved(verifierId);
}
function buildVerifierId(
Dimensions calldata dimensions,
uint256 externalActionId
) public pure returns (uint256) {
return
uint256(
keccak256(
abi.encode(
dimensions.tokenNumber,
dimensions.nullifierAmount,
dimensions.outputAmount,
externalActionId
)
)
);
}
function verifyProof(
uint256[2] calldata a,
uint256[2][2] calldata b,
uint256[2] calldata c,
uint256[] memory input,
uint256 verifierId
) internal view returns (bool) {
IVerifier verifier = verifierMap[verifierId];
require(
address(verifier) != address(0),
"Cannot find appropriate verifier"
);
return verifier.verifyProof(a, b, c, input, verifierId);
}
}
{
"compilationTarget": {
"contracts/Hinkal.sol": "Hinkal"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[{"components":[{"internalType":"uint128","name":"levels","type":"uint128"},{"internalType":"address","name":"poseidon2","type":"address"},{"internalType":"address","name":"poseidon4","type":"address"},{"internalType":"address","name":"poseidon5","type":"address"}],"internalType":"struct IMerkle.MerkleConstructorArgs","name":"constructorArgs","type":"tuple"},{"internalType":"address","name":"_hinkalHelper","type":"address"},{"internalType":"address","name":"_accessToken","type":"address"},{"internalType":"address","name":"_hinkalHelperManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"externalActionAddress","type":"address"}],"name":"ExternalActionRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"externalActionAddress","type":"address"}],"name":"ExternalActionRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"commitment","type":"uint256"},{"indexed":false,"internalType":"int256","name":"index","type":"int256"},{"indexed":false,"internalType":"bytes","name":"encryptedOutput","type":"bytes"}],"name":"NewCommitment","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"address","name":"erc20TokenAddress","type":"address"},{"indexed":false,"internalType":"int256","name":"publicAmount","type":"int256"}],"name":"NewTransaction","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"erc20Address","type":"address"},{"indexed":false,"internalType":"uint256","name":"randomization","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stealthAddress","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timeStamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NewUtxo","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nullifier","type":"uint256"}],"name":"Nullified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"ethereumAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"shieldedAddressHash","type":"bytes"}],"name":"Register","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"verifierId","type":"uint256"},{"indexed":false,"internalType":"address","name":"verifierAddress","type":"address"}],"name":"VerifierRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"verifierId","type":"uint256"}],"name":"VerifierRemoved","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HINKAL_HELPER_MANAGER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"accessToken","outputs":[{"internalType":"contract ICrossChainAccessToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"tokenNumber","type":"uint16"},{"internalType":"uint16","name":"nullifierAmount","type":"uint16"},{"internalType":"uint16","name":"outputAmount","type":"uint16"}],"internalType":"struct Dimensions","name":"dimensions","type":"tuple"},{"internalType":"uint256","name":"externalActionId","type":"uint256"}],"name":"buildVerifierId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRootHash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"}],"name":"hash2","outputs":[{"internalType":"uint256","name":"poseidonHash","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"a0","type":"uint256"},{"internalType":"uint256","name":"a1","type":"uint256"},{"internalType":"uint256","name":"a2","type":"uint256"},{"internalType":"uint256","name":"a3","type":"uint256"}],"name":"hash4","outputs":[{"internalType":"uint256","name":"poseidonHash","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"a0","type":"uint256"},{"internalType":"uint256","name":"a1","type":"uint256"},{"internalType":"uint256","name":"a2","type":"uint256"},{"internalType":"uint256","name":"a3","type":"uint256"},{"internalType":"uint256","name":"a4","type":"uint256"}],"name":"hash5","outputs":[{"internalType":"uint256","name":"poseidonHash","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hinkalHelper","outputs":[{"internalType":"contract IHinkalHelper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"logarithm2","outputs":[{"internalType":"uint256","name":"y","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"m_index","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nullifiers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poseidon2","outputs":[{"internalType":"contract IPoseidon2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poseidon4","outputs":[{"internalType":"contract IPoseidon4","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poseidon5","outputs":[{"internalType":"contract IPoseidon5","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"shieldedAddressHash","type":"bytes"}],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"externalActionId","type":"uint256"},{"internalType":"address","name":"externalActionAddress","type":"address"}],"name":"registerExternalAction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"verifierIds","type":"uint256[]"},{"internalType":"address[]","name":"verifierAddresses","type":"address[]"}],"name":"registerVerifiers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"externalActionId","type":"uint256"}],"name":"removeExternalAction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"verifierId","type":"uint256"}],"name":"removeVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_root","type":"uint256"}],"name":"rootHashExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rootIndex","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_accessToken","type":"address"}],"name":"setAccessToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_hinkalHelper","type":"address"}],"name":"setHinkalHelper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"a","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"b","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"c","type":"uint256[2]"},{"components":[{"internalType":"uint16","name":"tokenNumber","type":"uint16"},{"internalType":"uint16","name":"nullifierAmount","type":"uint16"},{"internalType":"uint16","name":"outputAmount","type":"uint16"}],"internalType":"struct Dimensions","name":"dimensions","type":"tuple"},{"components":[{"internalType":"uint256","name":"rootHashHinkal","type":"uint256"},{"internalType":"address[]","name":"erc20TokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"int256[]","name":"amountChanges","type":"int256[]"},{"internalType":"uint256[][]","name":"inputNullifiers","type":"uint256[][]"},{"internalType":"uint256[][]","name":"outCommitments","type":"uint256[][]"},{"internalType":"bytes[][]","name":"encryptedOutputs","type":"bytes[][]"},{"internalType":"uint256[]","name":"flatFees","type":"uint256[]"},{"internalType":"uint256","name":"timeStamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"extraRandomization","type":"uint256"},{"internalType":"uint256","name":"stealthAddress","type":"uint256"},{"internalType":"uint256","name":"H0","type":"uint256"},{"internalType":"uint256","name":"H1","type":"uint256"}],"internalType":"struct StealthAddressStructure","name":"stealthAddressStructure","type":"tuple"},{"internalType":"uint256","name":"rootHashAccessToken","type":"uint256"},{"internalType":"uint256","name":"calldataHash","type":"uint256"},{"internalType":"uint16","name":"publicSignalCount","type":"uint16"},{"internalType":"address","name":"relay","type":"address"},{"internalType":"address","name":"externalAddress","type":"address"},{"internalType":"uint256","name":"externalActionId","type":"uint256"},{"internalType":"bytes","name":"externalActionMetadata","type":"bytes"},{"components":[{"internalType":"address","name":"preHookContract","type":"address"},{"internalType":"address","name":"hookContract","type":"address"},{"internalType":"bytes","name":"preHookMetadata","type":"bytes"},{"internalType":"bytes","name":"postHookMetadata","type":"bytes"}],"internalType":"struct HookData","name":"hookData","type":"tuple"}],"internalType":"struct CircomData","name":"circomData","type":"tuple"}],"name":"transact","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"a","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"b","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"c","type":"uint256[2]"},{"components":[{"internalType":"uint16","name":"tokenNumber","type":"uint16"},{"internalType":"uint16","name":"nullifierAmount","type":"uint16"},{"internalType":"uint16","name":"outputAmount","type":"uint16"}],"internalType":"struct Dimensions","name":"dimensions","type":"tuple"},{"components":[{"internalType":"uint256","name":"rootHashHinkal","type":"uint256"},{"internalType":"address[]","name":"erc20TokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"int256[]","name":"amountChanges","type":"int256[]"},{"internalType":"uint256[][]","name":"inputNullifiers","type":"uint256[][]"},{"internalType":"uint256[][]","name":"outCommitments","type":"uint256[][]"},{"internalType":"bytes[][]","name":"encryptedOutputs","type":"bytes[][]"},{"internalType":"uint256[]","name":"flatFees","type":"uint256[]"},{"internalType":"uint256","name":"timeStamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"extraRandomization","type":"uint256"},{"internalType":"uint256","name":"stealthAddress","type":"uint256"},{"internalType":"uint256","name":"H0","type":"uint256"},{"internalType":"uint256","name":"H1","type":"uint256"}],"internalType":"struct StealthAddressStructure","name":"stealthAddressStructure","type":"tuple"},{"internalType":"uint256","name":"rootHashAccessToken","type":"uint256"},{"internalType":"uint256","name":"calldataHash","type":"uint256"},{"internalType":"uint16","name":"publicSignalCount","type":"uint16"},{"internalType":"address","name":"relay","type":"address"},{"internalType":"address","name":"externalAddress","type":"address"},{"internalType":"uint256","name":"externalActionId","type":"uint256"},{"internalType":"bytes","name":"externalActionMetadata","type":"bytes"},{"components":[{"internalType":"address","name":"preHookContract","type":"address"},{"internalType":"address","name":"hookContract","type":"address"},{"internalType":"bytes","name":"preHookMetadata","type":"bytes"},{"internalType":"bytes","name":"postHookMetadata","type":"bytes"}],"internalType":"struct HookData","name":"hookData","type":"tuple"}],"internalType":"struct CircomData","name":"circomData","type":"tuple"}],"name":"transactWithExternalAction","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"a","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"b","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"c","type":"uint256[2]"},{"components":[{"internalType":"uint16","name":"tokenNumber","type":"uint16"},{"internalType":"uint16","name":"nullifierAmount","type":"uint16"},{"internalType":"uint16","name":"outputAmount","type":"uint16"}],"internalType":"struct Dimensions","name":"dimensions","type":"tuple"},{"components":[{"internalType":"uint256","name":"rootHashHinkal","type":"uint256"},{"internalType":"address[]","name":"erc20TokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"int256[]","name":"amountChanges","type":"int256[]"},{"internalType":"uint256[][]","name":"inputNullifiers","type":"uint256[][]"},{"internalType":"uint256[][]","name":"outCommitments","type":"uint256[][]"},{"internalType":"bytes[][]","name":"encryptedOutputs","type":"bytes[][]"},{"internalType":"uint256[]","name":"flatFees","type":"uint256[]"},{"internalType":"uint256","name":"timeStamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"extraRandomization","type":"uint256"},{"internalType":"uint256","name":"stealthAddress","type":"uint256"},{"internalType":"uint256","name":"H0","type":"uint256"},{"internalType":"uint256","name":"H1","type":"uint256"}],"internalType":"struct StealthAddressStructure","name":"stealthAddressStructure","type":"tuple"},{"internalType":"uint256","name":"rootHashAccessToken","type":"uint256"},{"internalType":"uint256","name":"calldataHash","type":"uint256"},{"internalType":"uint16","name":"publicSignalCount","type":"uint16"},{"internalType":"address","name":"relay","type":"address"},{"internalType":"address","name":"externalAddress","type":"address"},{"internalType":"uint256","name":"externalActionId","type":"uint256"},{"internalType":"bytes","name":"externalActionMetadata","type":"bytes"},{"components":[{"internalType":"address","name":"preHookContract","type":"address"},{"internalType":"address","name":"hookContract","type":"address"},{"internalType":"bytes","name":"preHookMetadata","type":"bytes"},{"internalType":"bytes","name":"postHookMetadata","type":"bytes"}],"internalType":"struct HookData","name":"hookData","type":"tuple"}],"internalType":"struct CircomData","name":"circomData","type":"tuple"}],"name":"transactWithExternalActionAndHook","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"a","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"b","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"c","type":"uint256[2]"},{"components":[{"internalType":"uint16","name":"tokenNumber","type":"uint16"},{"internalType":"uint16","name":"nullifierAmount","type":"uint16"},{"internalType":"uint16","name":"outputAmount","type":"uint16"}],"internalType":"struct Dimensions","name":"dimensions","type":"tuple"},{"components":[{"internalType":"uint256","name":"rootHashHinkal","type":"uint256"},{"internalType":"address[]","name":"erc20TokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"int256[]","name":"amountChanges","type":"int256[]"},{"internalType":"uint256[][]","name":"inputNullifiers","type":"uint256[][]"},{"internalType":"uint256[][]","name":"outCommitments","type":"uint256[][]"},{"internalType":"bytes[][]","name":"encryptedOutputs","type":"bytes[][]"},{"internalType":"uint256[]","name":"flatFees","type":"uint256[]"},{"internalType":"uint256","name":"timeStamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"extraRandomization","type":"uint256"},{"internalType":"uint256","name":"stealthAddress","type":"uint256"},{"internalType":"uint256","name":"H0","type":"uint256"},{"internalType":"uint256","name":"H1","type":"uint256"}],"internalType":"struct StealthAddressStructure","name":"stealthAddressStructure","type":"tuple"},{"internalType":"uint256","name":"rootHashAccessToken","type":"uint256"},{"internalType":"uint256","name":"calldataHash","type":"uint256"},{"internalType":"uint16","name":"publicSignalCount","type":"uint16"},{"internalType":"address","name":"relay","type":"address"},{"internalType":"address","name":"externalAddress","type":"address"},{"internalType":"uint256","name":"externalActionId","type":"uint256"},{"internalType":"bytes","name":"externalActionMetadata","type":"bytes"},{"components":[{"internalType":"address","name":"preHookContract","type":"address"},{"internalType":"address","name":"hookContract","type":"address"},{"internalType":"bytes","name":"preHookMetadata","type":"bytes"},{"internalType":"bytes","name":"postHookMetadata","type":"bytes"}],"internalType":"struct HookData","name":"hookData","type":"tuple"}],"internalType":"struct CircomData","name":"circomData","type":"tuple"}],"name":"transactWithHook","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tree","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]