Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 16936409 | 586 days ago | IN | 0 ETH | 0.0614384 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
BundleController
Compiler Version
v0.8.2+commit.661d1103
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; import "PolicyController.sol"; import "CoreController.sol"; import "BundleToken.sol"; import "IProduct.sol"; import "IBundle.sol"; import "PoolController.sol"; contract BundleController is IBundle, CoreController { PolicyController private _policy; BundleToken private _token; mapping(uint256 /* bundleId */ => Bundle /* Bundle */) private _bundles; mapping(uint256 /* bundleId */ => uint256 /* activePolicyCount */) private _activePolicies; mapping(uint256 /* bundleId */ => mapping(bytes32 /* processId */ => uint256 /* lockedCapitalAmount */)) private _valueLockedPerPolicy; mapping(uint256 /* riskpoolId */ => uint256 /* numberOfUnburntBundles */) private _unburntBundlesForRiskpoolId; uint256 private _bundleCount; modifier onlyRiskpoolService() { require( _msgSender() == _getContractAddress("RiskpoolService"), "ERROR:BUC-001:NOT_RISKPOOL_SERVICE" ); _; } modifier onlyFundableBundle(uint256 bundleId) { Bundle storage bundle = _bundles[bundleId]; require(bundle.createdAt > 0, "ERROR:BUC-002:BUNDLE_DOES_NOT_EXIST"); require( bundle.state != IBundle.BundleState.Burned && bundle.state != IBundle.BundleState.Closed, "ERROR:BUC-003:BUNDLE_BURNED_OR_CLOSED" ); _; } function _afterInitialize() internal override onlyInitializing { _policy = PolicyController(_getContractAddress("Policy")); _token = BundleToken(_getContractAddress("BundleToken")); } function create(address owner_, uint riskpoolId_, bytes calldata filter_, uint256 amount_) external override onlyRiskpoolService returns(uint256 bundleId) { // will start with bundleId 1. // this helps in maps where a bundleId equals a non-existing entry bundleId = _bundleCount + 1; Bundle storage bundle = _bundles[bundleId]; require(bundle.createdAt == 0, "ERROR:BUC-010:BUNDLE_ALREADY_EXISTS"); // mint corresponding nft with bundleId as nft uint256 tokenId = _token.mint(bundleId, owner_); bundle.id = bundleId; bundle.tokenId = tokenId; bundle.riskpoolId = riskpoolId_; bundle.state = BundleState.Active; bundle.filter = filter_; bundle.capital = amount_; bundle.balance = amount_; bundle.createdAt = block.timestamp; bundle.updatedAt = block.timestamp; // update bundle count _bundleCount++; _unburntBundlesForRiskpoolId[riskpoolId_]++; emit LogBundleCreated(bundle.id, riskpoolId_, owner_, bundle.state, bundle.capital); } function fund(uint256 bundleId, uint256 amount) external override onlyRiskpoolService { Bundle storage bundle = _bundles[bundleId]; require(bundle.createdAt > 0, "ERROR:BUC-011:BUNDLE_DOES_NOT_EXIST"); require(bundle.state != IBundle.BundleState.Closed, "ERROR:BUC-012:BUNDLE_CLOSED"); bundle.capital += amount; bundle.balance += amount; bundle.updatedAt = block.timestamp; uint256 capacityAmount = bundle.capital - bundle.lockedCapital; emit LogBundleCapitalProvided(bundleId, _msgSender(), amount, capacityAmount); } function defund(uint256 bundleId, uint256 amount) external override onlyRiskpoolService { Bundle storage bundle = _bundles[bundleId]; require(bundle.createdAt > 0, "ERROR:BUC-013:BUNDLE_DOES_NOT_EXIST"); require( bundle.capital >= bundle.lockedCapital + amount || (bundle.lockedCapital == 0 && bundle.balance >= amount), "ERROR:BUC-014:CAPACITY_OR_BALANCE_TOO_LOW" ); if (bundle.capital >= amount) { bundle.capital -= amount; } else { bundle.capital = 0; } bundle.balance -= amount; bundle.updatedAt = block.timestamp; uint256 capacityAmount = bundle.capital - bundle.lockedCapital; emit LogBundleCapitalWithdrawn(bundleId, _msgSender(), amount, capacityAmount); } function lock(uint256 bundleId) external override onlyRiskpoolService { _changeState(bundleId, BundleState.Locked); } function unlock(uint256 bundleId) external override onlyRiskpoolService { _changeState(bundleId, BundleState.Active); } function close(uint256 bundleId) external override onlyRiskpoolService { require(_activePolicies[bundleId] == 0, "ERROR:BUC-015:BUNDLE_WITH_ACTIVE_POLICIES"); _changeState(bundleId, BundleState.Closed); } function burn(uint256 bundleId) external override onlyRiskpoolService { Bundle storage bundle = _bundles[bundleId]; require(bundle.state == BundleState.Closed, "ERROR:BUC-016:BUNDLE_NOT_CLOSED"); require(bundle.balance == 0, "ERROR:BUC-017:BUNDLE_HAS_BALANCE"); // burn corresponding nft -> as a result bundle looses its owner _token.burn(bundleId); _unburntBundlesForRiskpoolId[bundle.riskpoolId] -= 1; _changeState(bundleId, BundleState.Burned); } function collateralizePolicy(uint256 bundleId, bytes32 processId, uint256 amount) external override onlyRiskpoolService { IPolicy.Metadata memory metadata = _policy.getMetadata(processId); Bundle storage bundle = _bundles[bundleId]; require(bundle.riskpoolId == _getPoolController().getRiskPoolForProduct(metadata.productId), "ERROR:BUC-019:BUNDLE_NOT_IN_RISKPOOL"); require(bundle.createdAt > 0, "ERROR:BUC-020:BUNDLE_DOES_NOT_EXIST"); require(bundle.state == IBundle.BundleState.Active, "ERROR:BUC-021:BUNDLE_NOT_ACTIVE"); require(bundle.capital >= bundle.lockedCapital + amount, "ERROR:BUC-022:CAPACITY_TOO_LOW"); // might need to be added in a future relase require(_valueLockedPerPolicy[bundleId][processId] == 0, "ERROR:BUC-023:INCREMENTAL_COLLATERALIZATION_NOT_IMPLEMENTED"); bundle.lockedCapital += amount; bundle.updatedAt = block.timestamp; _activePolicies[bundleId] += 1; _valueLockedPerPolicy[bundleId][processId] = amount; uint256 capacityAmount = bundle.capital - bundle.lockedCapital; emit LogBundlePolicyCollateralized(bundleId, processId, amount, capacityAmount); } function processPremium(uint256 bundleId, bytes32 processId, uint256 amount) external override onlyRiskpoolService onlyFundableBundle(bundleId) { IPolicy.Policy memory policy = _policy.getPolicy(processId); require( policy.state != IPolicy.PolicyState.Closed, "ERROR:POL-030:POLICY_STATE_INVALID" ); Bundle storage bundle = _bundles[bundleId]; require(bundle.createdAt > 0, "ERROR:BUC-031:BUNDLE_DOES_NOT_EXIST"); bundle.balance += amount; bundle.updatedAt = block.timestamp; // solhint-disable-line } function processPayout(uint256 bundleId, bytes32 processId, uint256 amount) external override onlyRiskpoolService { IPolicy.Policy memory policy = _policy.getPolicy(processId); require( policy.state != IPolicy.PolicyState.Closed, "ERROR:POL-040:POLICY_STATE_INVALID" ); // check there are policies and there is sufficient locked capital for policy require(_activePolicies[bundleId] > 0, "ERROR:BUC-041:NO_ACTIVE_POLICIES_FOR_BUNDLE"); require(_valueLockedPerPolicy[bundleId][processId] >= amount, "ERROR:BUC-042:COLLATERAL_INSUFFICIENT_FOR_POLICY"); // make sure bundle exists and is not yet closed Bundle storage bundle = _bundles[bundleId]; require(bundle.createdAt > 0, "ERROR:BUC-043:BUNDLE_DOES_NOT_EXIST"); require( bundle.state == IBundle.BundleState.Active || bundle.state == IBundle.BundleState.Locked, "ERROR:BUC-044:BUNDLE_STATE_INVALID"); require(bundle.capital >= amount, "ERROR:BUC-045:CAPITAL_TOO_LOW"); require(bundle.lockedCapital >= amount, "ERROR:BUC-046:LOCKED_CAPITAL_TOO_LOW"); require(bundle.balance >= amount, "ERROR:BUC-047:BALANCE_TOO_LOW"); _valueLockedPerPolicy[bundleId][processId] -= amount; bundle.capital -= amount; bundle.lockedCapital -= amount; bundle.balance -= amount; bundle.updatedAt = block.timestamp; // solhint-disable-line emit LogBundlePayoutProcessed(bundleId, processId, amount); } function releasePolicy(uint256 bundleId, bytes32 processId) external override onlyRiskpoolService returns(uint256 remainingCollateralAmount) { IPolicy.Policy memory policy = _policy.getPolicy(processId); require( policy.state == IPolicy.PolicyState.Closed, "ERROR:POL-050:POLICY_STATE_INVALID" ); // make sure bundle exists and is not yet closed Bundle storage bundle = _bundles[bundleId]; require(bundle.createdAt > 0, "ERROR:BUC-051:BUNDLE_DOES_NOT_EXIST"); require(_activePolicies[bundleId] > 0, "ERROR:BUC-052:NO_ACTIVE_POLICIES_FOR_BUNDLE"); uint256 lockedForPolicyAmount = _valueLockedPerPolicy[bundleId][processId]; // this should never ever fail ... require( bundle.lockedCapital >= lockedForPolicyAmount, "PANIC:BUC-053:UNLOCK_CAPITAL_TOO_BIG" ); // policy no longer relevant for bundle _activePolicies[bundleId] -= 1; delete _valueLockedPerPolicy[bundleId][processId]; // update bundle capital bundle.lockedCapital -= lockedForPolicyAmount; bundle.updatedAt = block.timestamp; // solhint-disable-line uint256 capacityAmount = bundle.capital - bundle.lockedCapital; emit LogBundlePolicyReleased(bundleId, processId, lockedForPolicyAmount, capacityAmount); } function getOwner(uint256 bundleId) public view returns(address) { uint256 tokenId = getBundle(bundleId).tokenId; return _token.ownerOf(tokenId); } function getState(uint256 bundleId) public view returns(BundleState) { return getBundle(bundleId).state; } function getFilter(uint256 bundleId) public view returns(bytes memory) { return getBundle(bundleId).filter; } function getCapacity(uint256 bundleId) public view returns(uint256) { Bundle memory bundle = getBundle(bundleId); return bundle.capital - bundle.lockedCapital; } function getTotalValueLocked(uint256 bundleId) public view returns(uint256) { return getBundle(bundleId).lockedCapital; } function getBalance(uint256 bundleId) public view returns(uint256) { return getBundle(bundleId).balance; } function getToken() external view returns(BundleToken) { return _token; } function getBundle(uint256 bundleId) public view returns(Bundle memory) { Bundle memory bundle = _bundles[bundleId]; require(bundle.createdAt > 0, "ERROR:BUC-060:BUNDLE_DOES_NOT_EXIST"); return bundle; } function bundles() public view returns(uint256) { return _bundleCount; } function unburntBundles(uint256 riskpoolId) external view returns(uint256) { return _unburntBundlesForRiskpoolId[riskpoolId]; } function _getPoolController() internal view returns (PoolController _poolController) { _poolController = PoolController(_getContractAddress("Pool")); } function _changeState(uint256 bundleId, BundleState newState) internal { BundleState oldState = getState(bundleId); _checkStateTransition(oldState, newState); _setState(bundleId, newState); // log entry for successful state change emit LogBundleStateChanged(bundleId, oldState, newState); } function _setState(uint256 bundleId, BundleState newState) internal { _bundles[bundleId].state = newState; _bundles[bundleId].updatedAt = block.timestamp; } function _checkStateTransition(BundleState oldState, BundleState newState) internal pure { if (oldState == BundleState.Active) { require( newState == BundleState.Locked || newState == BundleState.Closed, "ERROR:BUC-070:ACTIVE_INVALID_TRANSITION" ); } else if (oldState == BundleState.Locked) { require( newState == BundleState.Active || newState == BundleState.Closed, "ERROR:BUC-071:LOCKED_INVALID_TRANSITION" ); } else if (oldState == BundleState.Closed) { require( newState == BundleState.Burned, "ERROR:BUC-072:CLOSED_INVALID_TRANSITION" ); } else if (oldState == BundleState.Burned) { revert("ERROR:BUC-073:BURNED_IS_FINAL_STATE"); } else { revert("ERROR:BOC-074:INITIAL_STATE_NOT_HANDLED"); } } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; import "CoreController.sol"; import "ComponentController.sol"; import "IPolicy.sol"; contract PolicyController is IPolicy, CoreController { // bytes32 public constant NAME = "PolicyController"; // Metadata mapping(bytes32 /* processId */ => Metadata) public metadata; // Applications mapping(bytes32 /* processId */ => Application) public applications; // Policies mapping(bytes32 /* processId */ => Policy) public policies; // Claims mapping(bytes32 /* processId */ => mapping(uint256 /* claimId */ => Claim)) public claims; // Payouts mapping(bytes32 /* processId */ => mapping(uint256 /* payoutId */ => Payout)) public payouts; mapping(bytes32 /* processId */ => uint256) public payoutCount; // counter for assigned processIds, used to ensure unique processIds uint256 private _assigendProcessIds; ComponentController private _component; function _afterInitialize() internal override onlyInitializing { _component = ComponentController(_getContractAddress("Component")); } /* Metadata */ function createPolicyFlow( address owner, uint256 productId, bytes calldata data ) external override onlyPolicyFlow("Policy") returns(bytes32 processId) { require(owner != address(0), "ERROR:POL-001:INVALID_OWNER"); require(_component.isProduct(productId), "ERROR:POL-002:INVALID_PRODUCT"); require(_component.getComponentState(productId) == IComponent.ComponentState.Active, "ERROR:POL-003:PRODUCT_NOT_ACTIVE"); processId = _generateNextProcessId(); Metadata storage meta = metadata[processId]; require(meta.createdAt == 0, "ERROR:POC-004:METADATA_ALREADY_EXISTS"); meta.owner = owner; meta.productId = productId; meta.state = PolicyFlowState.Started; meta.data = data; meta.createdAt = block.timestamp; // solhint-disable-line meta.updatedAt = block.timestamp; // solhint-disable-line emit LogMetadataCreated(owner, processId, productId, PolicyFlowState.Started); } /* Application */ function createApplication( bytes32 processId, uint256 premiumAmount, uint256 sumInsuredAmount, bytes calldata data ) external override onlyPolicyFlow("Policy") { Metadata storage meta = metadata[processId]; require(meta.createdAt > 0, "ERROR:POC-010:METADATA_DOES_NOT_EXIST"); Application storage application = applications[processId]; require(application.createdAt == 0, "ERROR:POC-011:APPLICATION_ALREADY_EXISTS"); require(premiumAmount > 0, "ERROR:POC-012:PREMIUM_AMOUNT_ZERO"); require(sumInsuredAmount > premiumAmount, "ERROR:POC-013:SUM_INSURED_AMOUNT_TOO_SMALL"); application.state = ApplicationState.Applied; application.premiumAmount = premiumAmount; application.sumInsuredAmount = sumInsuredAmount; application.data = data; application.createdAt = block.timestamp; // solhint-disable-line application.updatedAt = block.timestamp; // solhint-disable-line meta.state = PolicyFlowState.Active; meta.updatedAt = block.timestamp; // solhint-disable-line emit LogMetadataStateChanged(processId, meta.state); emit LogApplicationCreated(processId, premiumAmount, sumInsuredAmount); } function collectPremium(bytes32 processId, uint256 amount) external override { Policy storage policy = policies[processId]; require(policy.createdAt > 0, "ERROR:POC-110:POLICY_DOES_NOT_EXIST"); require(policy.premiumPaidAmount + amount <= policy.premiumExpectedAmount, "ERROR:POC-111:AMOUNT_TOO_BIG"); policy.premiumPaidAmount += amount; policy.updatedAt = block.timestamp; // solhint-disable-line emit LogPremiumCollected(processId, amount); } function revokeApplication(bytes32 processId) external override onlyPolicyFlow("Policy") { Metadata storage meta = metadata[processId]; require(meta.createdAt > 0, "ERROR:POC-014:METADATA_DOES_NOT_EXIST"); Application storage application = applications[processId]; require(application.createdAt > 0, "ERROR:POC-015:APPLICATION_DOES_NOT_EXIST"); require(application.state == ApplicationState.Applied, "ERROR:POC-016:APPLICATION_STATE_INVALID"); application.state = ApplicationState.Revoked; application.updatedAt = block.timestamp; // solhint-disable-line meta.state = PolicyFlowState.Finished; meta.updatedAt = block.timestamp; // solhint-disable-line emit LogMetadataStateChanged(processId, meta.state); emit LogApplicationRevoked(processId); } function underwriteApplication(bytes32 processId) external override onlyPolicyFlow("Policy") { Application storage application = applications[processId]; require(application.createdAt > 0, "ERROR:POC-017:APPLICATION_DOES_NOT_EXIST"); require(application.state == ApplicationState.Applied, "ERROR:POC-018:APPLICATION_STATE_INVALID"); application.state = ApplicationState.Underwritten; application.updatedAt = block.timestamp; // solhint-disable-line emit LogApplicationUnderwritten(processId); } function declineApplication(bytes32 processId) external override onlyPolicyFlow("Policy") { Metadata storage meta = metadata[processId]; require(meta.createdAt > 0, "ERROR:POC-019:METADATA_DOES_NOT_EXIST"); Application storage application = applications[processId]; require(application.createdAt > 0, "ERROR:POC-020:APPLICATION_DOES_NOT_EXIST"); require(application.state == ApplicationState.Applied, "ERROR:POC-021:APPLICATION_STATE_INVALID"); application.state = ApplicationState.Declined; application.updatedAt = block.timestamp; // solhint-disable-line meta.state = PolicyFlowState.Finished; meta.updatedAt = block.timestamp; // solhint-disable-line emit LogMetadataStateChanged(processId, meta.state); emit LogApplicationDeclined(processId); } /* Policy */ function createPolicy(bytes32 processId) external override onlyPolicyFlow("Policy") { Application memory application = applications[processId]; require(application.createdAt > 0 && application.state == ApplicationState.Underwritten, "ERROR:POC-022:APPLICATION_ACCESS_INVALID"); Policy storage policy = policies[processId]; require(policy.createdAt == 0, "ERROR:POC-023:POLICY_ALREADY_EXISTS"); policy.state = PolicyState.Active; policy.premiumExpectedAmount = application.premiumAmount; policy.payoutMaxAmount = application.sumInsuredAmount; policy.createdAt = block.timestamp; // solhint-disable-line policy.updatedAt = block.timestamp; // solhint-disable-line emit LogPolicyCreated(processId); } function adjustPremiumSumInsured( bytes32 processId, uint256 expectedPremiumAmount, uint256 sumInsuredAmount ) external override onlyPolicyFlow("Policy") { Application storage application = applications[processId]; require( application.createdAt > 0 && application.state == ApplicationState.Underwritten, "ERROR:POC-024:APPLICATION_ACCESS_INVALID"); require( sumInsuredAmount <= application.sumInsuredAmount, "ERROR:POC-026:APPLICATION_SUM_INSURED_INCREASE_INVALID"); Policy storage policy = policies[processId]; require( policy.createdAt > 0 && policy.state == IPolicy.PolicyState.Active, "ERROR:POC-027:POLICY_ACCESS_INVALID"); require( expectedPremiumAmount > 0 && expectedPremiumAmount >= policy.premiumPaidAmount && expectedPremiumAmount < sumInsuredAmount, "ERROR:POC-025:APPLICATION_PREMIUM_INVALID"); if (sumInsuredAmount != application.sumInsuredAmount) { emit LogApplicationSumInsuredAdjusted(processId, application.sumInsuredAmount, sumInsuredAmount); application.sumInsuredAmount = sumInsuredAmount; application.updatedAt = block.timestamp; // solhint-disable-line policy.payoutMaxAmount = sumInsuredAmount; policy.updatedAt = block.timestamp; // solhint-disable-line } if (expectedPremiumAmount != application.premiumAmount) { emit LogApplicationPremiumAdjusted(processId, application.premiumAmount, expectedPremiumAmount); application.premiumAmount = expectedPremiumAmount; application.updatedAt = block.timestamp; // solhint-disable-line emit LogPolicyPremiumAdjusted(processId, policy.premiumExpectedAmount, expectedPremiumAmount); policy.premiumExpectedAmount = expectedPremiumAmount; policy.updatedAt = block.timestamp; // solhint-disable-line } } function expirePolicy(bytes32 processId) external override onlyPolicyFlow("Policy") { Policy storage policy = policies[processId]; require(policy.createdAt > 0, "ERROR:POC-028:POLICY_DOES_NOT_EXIST"); require(policy.state == PolicyState.Active, "ERROR:POC-029:APPLICATION_STATE_INVALID"); policy.state = PolicyState.Expired; policy.updatedAt = block.timestamp; // solhint-disable-line emit LogPolicyExpired(processId); } function closePolicy(bytes32 processId) external override onlyPolicyFlow("Policy") { Metadata storage meta = metadata[processId]; require(meta.createdAt > 0, "ERROR:POC-030:METADATA_DOES_NOT_EXIST"); Policy storage policy = policies[processId]; require(policy.createdAt > 0, "ERROR:POC-031:POLICY_DOES_NOT_EXIST"); require(policy.state == PolicyState.Expired, "ERROR:POC-032:POLICY_STATE_INVALID"); require(policy.openClaimsCount == 0, "ERROR:POC-033:POLICY_HAS_OPEN_CLAIMS"); policy.state = PolicyState.Closed; policy.updatedAt = block.timestamp; // solhint-disable-line meta.state = PolicyFlowState.Finished; meta.updatedAt = block.timestamp; // solhint-disable-line emit LogMetadataStateChanged(processId, meta.state); emit LogPolicyClosed(processId); } /* Claim */ function createClaim( bytes32 processId, uint256 claimAmount, bytes calldata data ) external override onlyPolicyFlow("Policy") returns (uint256 claimId) { Policy storage policy = policies[processId]; require(policy.createdAt > 0, "ERROR:POC-040:POLICY_DOES_NOT_EXIST"); require(policy.state == IPolicy.PolicyState.Active, "ERROR:POC-041:POLICY_NOT_ACTIVE"); // no validation of claimAmount > 0 here to explicitly allow claims with amount 0. This can be useful for parametric insurance // to have proof that the claim calculation was executed without entitlement to payment. require(policy.payoutAmount + claimAmount <= policy.payoutMaxAmount, "ERROR:POC-042:CLAIM_AMOUNT_EXCEEDS_MAX_PAYOUT"); claimId = policy.claimsCount; Claim storage claim = claims[processId][claimId]; require(claim.createdAt == 0, "ERROR:POC-043:CLAIM_ALREADY_EXISTS"); claim.state = ClaimState.Applied; claim.claimAmount = claimAmount; claim.data = data; claim.createdAt = block.timestamp; // solhint-disable-line claim.updatedAt = block.timestamp; // solhint-disable-line policy.claimsCount++; policy.openClaimsCount++; policy.updatedAt = block.timestamp; // solhint-disable-line emit LogClaimCreated(processId, claimId, claimAmount); } function confirmClaim( bytes32 processId, uint256 claimId, uint256 confirmedAmount ) external override onlyPolicyFlow("Policy") { Policy storage policy = policies[processId]; require(policy.createdAt > 0, "ERROR:POC-050:POLICY_DOES_NOT_EXIST"); require(policy.openClaimsCount > 0, "ERROR:POC-051:POLICY_WITHOUT_OPEN_CLAIMS"); // no validation of claimAmount > 0 here as is it possible to have claims with amount 0 (see createClaim()). require(policy.payoutAmount + confirmedAmount <= policy.payoutMaxAmount, "ERROR:POC-052:PAYOUT_MAX_AMOUNT_EXCEEDED"); Claim storage claim = claims[processId][claimId]; require(claim.createdAt > 0, "ERROR:POC-053:CLAIM_DOES_NOT_EXIST"); require(claim.state == ClaimState.Applied, "ERROR:POC-054:CLAIM_STATE_INVALID"); claim.state = ClaimState.Confirmed; claim.claimAmount = confirmedAmount; claim.updatedAt = block.timestamp; // solhint-disable-line policy.payoutAmount += confirmedAmount; policy.updatedAt = block.timestamp; // solhint-disable-line emit LogClaimConfirmed(processId, claimId, confirmedAmount); } function declineClaim(bytes32 processId, uint256 claimId) external override onlyPolicyFlow("Policy") { Policy storage policy = policies[processId]; require(policy.createdAt > 0, "ERROR:POC-060:POLICY_DOES_NOT_EXIST"); require(policy.openClaimsCount > 0, "ERROR:POC-061:POLICY_WITHOUT_OPEN_CLAIMS"); Claim storage claim = claims[processId][claimId]; require(claim.createdAt > 0, "ERROR:POC-062:CLAIM_DOES_NOT_EXIST"); require(claim.state == ClaimState.Applied, "ERROR:POC-063:CLAIM_STATE_INVALID"); claim.state = ClaimState.Declined; claim.updatedAt = block.timestamp; // solhint-disable-line policy.updatedAt = block.timestamp; // solhint-disable-line emit LogClaimDeclined(processId, claimId); } function closeClaim(bytes32 processId, uint256 claimId) external override onlyPolicyFlow("Policy") { Policy storage policy = policies[processId]; require(policy.createdAt > 0, "ERROR:POC-070:POLICY_DOES_NOT_EXIST"); require(policy.openClaimsCount > 0, "ERROR:POC-071:POLICY_WITHOUT_OPEN_CLAIMS"); Claim storage claim = claims[processId][claimId]; require(claim.createdAt > 0, "ERROR:POC-072:CLAIM_DOES_NOT_EXIST"); require( claim.state == ClaimState.Confirmed || claim.state == ClaimState.Declined, "ERROR:POC-073:CLAIM_STATE_INVALID"); require( (claim.state == ClaimState.Confirmed && claim.claimAmount == claim.paidAmount) || (claim.state == ClaimState.Declined), "ERROR:POC-074:CLAIM_WITH_UNPAID_PAYOUTS" ); claim.state = ClaimState.Closed; claim.updatedAt = block.timestamp; // solhint-disable-line policy.openClaimsCount--; policy.updatedAt = block.timestamp; // solhint-disable-line emit LogClaimClosed(processId, claimId); } /* Payout */ function createPayout( bytes32 processId, uint256 claimId, uint256 payoutAmount, bytes calldata data ) external override onlyPolicyFlow("Policy") returns (uint256 payoutId) { Policy storage policy = policies[processId]; require(policy.createdAt > 0, "ERROR:POC-080:POLICY_DOES_NOT_EXIST"); Claim storage claim = claims[processId][claimId]; require(claim.createdAt > 0, "ERROR:POC-081:CLAIM_DOES_NOT_EXIST"); require(claim.state == IPolicy.ClaimState.Confirmed, "ERROR:POC-082:CLAIM_NOT_CONFIRMED"); require(payoutAmount > 0, "ERROR:POC-083:PAYOUT_AMOUNT_ZERO_INVALID"); require( claim.paidAmount + payoutAmount <= claim.claimAmount, "ERROR:POC-084:PAYOUT_AMOUNT_TOO_BIG" ); payoutId = payoutCount[processId]; Payout storage payout = payouts[processId][payoutId]; require(payout.createdAt == 0, "ERROR:POC-085:PAYOUT_ALREADY_EXISTS"); payout.claimId = claimId; payout.amount = payoutAmount; payout.data = data; payout.state = PayoutState.Expected; payout.createdAt = block.timestamp; // solhint-disable-line payout.updatedAt = block.timestamp; // solhint-disable-line payoutCount[processId]++; policy.updatedAt = block.timestamp; // solhint-disable-line emit LogPayoutCreated(processId, claimId, payoutId, payoutAmount); } function processPayout( bytes32 processId, uint256 payoutId ) external override onlyPolicyFlow("Policy") { Policy storage policy = policies[processId]; require(policy.createdAt > 0, "ERROR:POC-090:POLICY_DOES_NOT_EXIST"); require(policy.openClaimsCount > 0, "ERROR:POC-091:POLICY_WITHOUT_OPEN_CLAIMS"); Payout storage payout = payouts[processId][payoutId]; require(payout.createdAt > 0, "ERROR:POC-092:PAYOUT_DOES_NOT_EXIST"); require(payout.state == PayoutState.Expected, "ERROR:POC-093:PAYOUT_ALREADY_PAIDOUT"); payout.state = IPolicy.PayoutState.PaidOut; payout.updatedAt = block.timestamp; // solhint-disable-line emit LogPayoutProcessed(processId, payoutId); Claim storage claim = claims[processId][payout.claimId]; claim.paidAmount += payout.amount; claim.updatedAt = block.timestamp; // solhint-disable-line // check if claim can be closed if (claim.claimAmount == claim.paidAmount) { claim.state = IPolicy.ClaimState.Closed; policy.openClaimsCount -= 1; policy.updatedAt = block.timestamp; // solhint-disable-line emit LogClaimClosed(processId, payout.claimId); } } function getMetadata(bytes32 processId) public view returns (IPolicy.Metadata memory _metadata) { _metadata = metadata[processId]; require(_metadata.createdAt > 0, "ERROR:POC-100:METADATA_DOES_NOT_EXIST"); } function getApplication(bytes32 processId) public view returns (IPolicy.Application memory application) { application = applications[processId]; require(application.createdAt > 0, "ERROR:POC-101:APPLICATION_DOES_NOT_EXIST"); } function getNumberOfClaims(bytes32 processId) external view returns(uint256 numberOfClaims) { numberOfClaims = getPolicy(processId).claimsCount; } function getNumberOfPayouts(bytes32 processId) external view returns(uint256 numberOfPayouts) { numberOfPayouts = payoutCount[processId]; } function getPolicy(bytes32 processId) public view returns (IPolicy.Policy memory policy) { policy = policies[processId]; require(policy.createdAt > 0, "ERROR:POC-102:POLICY_DOES_NOT_EXIST"); } function getClaim(bytes32 processId, uint256 claimId) public view returns (IPolicy.Claim memory claim) { claim = claims[processId][claimId]; require(claim.createdAt > 0, "ERROR:POC-103:CLAIM_DOES_NOT_EXIST"); } function getPayout(bytes32 processId, uint256 payoutId) public view returns (IPolicy.Payout memory payout) { payout = payouts[processId][payoutId]; require(payout.createdAt > 0, "ERROR:POC-104:PAYOUT_DOES_NOT_EXIST"); } function processIds() external view returns (uint256) { return _assigendProcessIds; } function _generateNextProcessId() private returns(bytes32 processId) { _assigendProcessIds++; processId = keccak256( abi.encodePacked( block.chainid, address(_registry), _assigendProcessIds ) ); } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; import "IAccess.sol"; import "IRegistry.sol"; import "Initializable.sol"; import "Context.sol"; contract CoreController is Context, Initializable { IRegistry internal _registry; IAccess internal _access; constructor () { _disableInitializers(); } modifier onlyInstanceOperator() { require( _registry.ensureSender(_msgSender(), "InstanceOperatorService"), "ERROR:CRC-001:NOT_INSTANCE_OPERATOR"); _; } modifier onlyPolicyFlow(bytes32 module) { // Allow only from delegator require( address(this) == _getContractAddress(module), "ERROR:CRC-002:NOT_ON_STORAGE" ); // Allow only ProductService (it delegates to PolicyFlow) require( _msgSender() == _getContractAddress("ProductService"), "ERROR:CRC-003:NOT_PRODUCT_SERVICE" ); _; } function initialize(address registry) public initializer { _registry = IRegistry(registry); if (_getName() != "Access") { _access = IAccess(_getContractAddress("Access")); } _afterInitialize(); } function _getName() internal virtual pure returns(bytes32) { return ""; } function _afterInitialize() internal virtual onlyInitializing {} function _getContractAddress(bytes32 contractName) internal view returns (address contractAddress) { contractAddress = _registry.getContract(contractName); require( contractAddress != address(0), "ERROR:CRC-004:CONTRACT_NOT_REGISTERED" ); } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; interface IAccess { function getDefaultAdminRole() external view returns(bytes32 role); function getProductOwnerRole() external view returns(bytes32 role); function getOracleProviderRole() external view returns(bytes32 role); function getRiskpoolKeeperRole() external view returns(bytes32 role); function hasRole(bytes32 role, address principal) external view returns(bool); function grantRole(bytes32 role, address principal) external; function revokeRole(bytes32 role, address principal) external; function renounceRole(bytes32 role, address principal) external; function addRole(bytes32 role) external; function invalidateRole(bytes32 role) external; }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; interface IRegistry { event LogContractRegistered( bytes32 release, bytes32 contractName, address contractAddress, bool isNew ); event LogContractDeregistered(bytes32 release, bytes32 contractName); event LogReleasePrepared(bytes32 release); function registerInRelease( bytes32 _release, bytes32 _contractName, address _contractAddress ) external; function register(bytes32 _contractName, address _contractAddress) external; function deregisterInRelease(bytes32 _release, bytes32 _contractName) external; function deregister(bytes32 _contractName) external; function prepareRelease(bytes32 _newRelease) external; function getContractInRelease(bytes32 _release, bytes32 _contractName) external view returns (address _contractAddress); function getContract(bytes32 _contractName) external view returns (address _contractAddress); function getRelease() external view returns (bytes32 _release); function ensureSender(address sender, bytes32 _contractName) external view returns(bool _senderMatches); function contracts() external view returns (uint256 _numberOfContracts); function contractName(uint256 idx) external view returns (bytes32 _contractName); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "Address.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. Equivalent to `reinitializer(1)`. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original * initialization step. This is essential to configure modules that are added through upgrades and that require * initialization. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ 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"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ 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"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ 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"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; import "CoreController.sol"; import "IComponent.sol"; import "IOracle.sol"; import "IProduct.sol"; import "IRiskpool.sol"; import "IComponentEvents.sol"; import "EnumerableSet.sol"; contract ComponentController is IComponentEvents, CoreController { using EnumerableSet for EnumerableSet.UintSet; mapping(uint256 => IComponent) private _componentById; mapping(bytes32 => uint256) private _componentIdByName; mapping(address => uint256) private _componentIdByAddress; mapping(uint256 => IComponent.ComponentState) private _componentState; EnumerableSet.UintSet private _products; EnumerableSet.UintSet private _oracles; EnumerableSet.UintSet private _riskpools; uint256 private _componentCount; mapping(uint256 /* product id */ => address /* policy flow address */) private _policyFlowByProductId; modifier onlyComponentOwnerService() { require( _msgSender() == _getContractAddress("ComponentOwnerService"), "ERROR:CCR-001:NOT_COMPONENT_OWNER_SERVICE"); _; } modifier onlyInstanceOperatorService() { require( _msgSender() == _getContractAddress("InstanceOperatorService"), "ERROR:CCR-002:NOT_INSTANCE_OPERATOR_SERVICE"); _; } function propose(IComponent component) external onlyComponentOwnerService { // input validation require(_componentIdByAddress[address(component)] == 0, "ERROR:CCR-003:COMPONENT_ALREADY_EXISTS"); require(_componentIdByName[component.getName()] == 0, "ERROR:CCR-004:COMPONENT_NAME_ALREADY_EXISTS"); // assigning id and persisting component uint256 id = _persistComponent(component); // log entry for successful proposal emit LogComponentProposed( component.getName(), component.getType(), address(component), id); // inform component about successful proposal component.proposalCallback(); } function _persistComponent(IComponent component) internal returns(uint256 id) { // fetch next component id _componentCount++; id = _componentCount; // update component state _changeState(id, IComponent.ComponentState.Proposed); component.setId(id); // update controller book keeping _componentById[id] = component; _componentIdByName[component.getName()] = id; _componentIdByAddress[address(component)] = id; // type specific book keeping if (component.isProduct()) { EnumerableSet.add(_products, id); } else if (component.isOracle()) { EnumerableSet.add(_oracles, id); } else if (component.isRiskpool()) { EnumerableSet.add(_riskpools, id); } } function exists(uint256 id) public view returns(bool) { IComponent component = _componentById[id]; return (address(component) != address(0)); } function approve(uint256 id) external onlyInstanceOperatorService { _changeState(id, IComponent.ComponentState.Active); IComponent component = getComponent(id); if (isProduct(id)) { _policyFlowByProductId[id] = IProduct(address(component)).getPolicyFlow(); } emit LogComponentApproved(id); // inform component about successful approval component.approvalCallback(); } function decline(uint256 id) external onlyInstanceOperatorService { _changeState(id, IComponent.ComponentState.Declined); emit LogComponentDeclined(id); // inform component about decline IComponent component = getComponent(id); component.declineCallback(); } function suspend(uint256 id) external onlyInstanceOperatorService { _changeState(id, IComponent.ComponentState.Suspended); emit LogComponentSuspended(id); // inform component about suspending IComponent component = getComponent(id); component.suspendCallback(); } function resume(uint256 id) external onlyInstanceOperatorService { _changeState(id, IComponent.ComponentState.Active); emit LogComponentResumed(id); // inform component about resuming IComponent component = getComponent(id); component.resumeCallback(); } function pause(uint256 id) external onlyComponentOwnerService { _changeState(id, IComponent.ComponentState.Paused); emit LogComponentPaused(id); // inform component about pausing IComponent component = getComponent(id); component.pauseCallback(); } function unpause(uint256 id) external onlyComponentOwnerService { _changeState(id, IComponent.ComponentState.Active); emit LogComponentUnpaused(id); // inform component about unpausing IComponent component = getComponent(id); component.unpauseCallback(); } function archiveFromComponentOwner(uint256 id) external onlyComponentOwnerService { _changeState(id, IComponent.ComponentState.Archived); emit LogComponentArchived(id); // inform component about archiving IComponent component = getComponent(id); component.archiveCallback(); } function archiveFromInstanceOperator(uint256 id) external onlyInstanceOperatorService { _changeState(id, IComponent.ComponentState.Archived); emit LogComponentArchived(id); // inform component about archiving IComponent component = getComponent(id); component.archiveCallback(); } function getComponent(uint256 id) public view returns (IComponent component) { component = _componentById[id]; require(address(component) != address(0), "ERROR:CCR-005:INVALID_COMPONENT_ID"); } function getComponentId(address componentAddress) public view returns (uint256 id) { require(componentAddress != address(0), "ERROR:CCR-006:COMPONENT_ADDRESS_ZERO"); id = _componentIdByAddress[componentAddress]; require(id > 0, "ERROR:CCR-007:COMPONENT_UNKNOWN"); } function getComponentType(uint256 id) public view returns (IComponent.ComponentType componentType) { if (EnumerableSet.contains(_products, id)) { return IComponent.ComponentType.Product; } else if (EnumerableSet.contains(_oracles, id)) { return IComponent.ComponentType.Oracle; } else if (EnumerableSet.contains(_riskpools, id)) { return IComponent.ComponentType.Riskpool; } else { revert("ERROR:CCR-008:INVALID_COMPONENT_ID"); } } function getComponentState(uint256 id) public view returns (IComponent.ComponentState componentState) { return _componentState[id]; } function getOracleId(uint256 idx) public view returns (uint256 oracleId) { return EnumerableSet.at(_oracles, idx); } function getRiskpoolId(uint256 idx) public view returns (uint256 riskpoolId) { return EnumerableSet.at(_riskpools, idx); } function getProductId(uint256 idx) public view returns (uint256 productId) { return EnumerableSet.at(_products, idx); } function getRequiredRole(IComponent.ComponentType componentType) external view returns (bytes32) { if (componentType == IComponent.ComponentType.Product) { return _access.getProductOwnerRole(); } else if (componentType == IComponent.ComponentType.Oracle) { return _access.getOracleProviderRole(); } else if (componentType == IComponent.ComponentType.Riskpool) { return _access.getRiskpoolKeeperRole(); } else { revert("ERROR:CCR-010:COMPONENT_TYPE_UNKNOWN"); } } function components() public view returns (uint256 count) { return _componentCount; } function products() public view returns (uint256 count) { return EnumerableSet.length(_products); } function oracles() public view returns (uint256 count) { return EnumerableSet.length(_oracles); } function riskpools() public view returns (uint256 count) { return EnumerableSet.length(_riskpools); } function isProduct(uint256 id) public view returns (bool) { return EnumerableSet.contains(_products, id); } function isOracle(uint256 id) public view returns (bool) { return EnumerableSet.contains(_oracles, id); } function isRiskpool(uint256 id) public view returns (bool) { return EnumerableSet.contains(_riskpools, id); } function getPolicyFlow(uint256 productId) public view returns (address _policyFlow) { require(isProduct(productId), "ERROR:CCR-011:UNKNOWN_PRODUCT_ID"); _policyFlow = _policyFlowByProductId[productId]; } function _changeState(uint256 componentId, IComponent.ComponentState newState) internal { IComponent.ComponentState oldState = _componentState[componentId]; _checkStateTransition(oldState, newState); _componentState[componentId] = newState; // log entry for successful component state change emit LogComponentStateChanged(componentId, oldState, newState); } function _checkStateTransition( IComponent.ComponentState oldState, IComponent.ComponentState newState ) internal pure { require(newState != oldState, "ERROR:CCR-020:SOURCE_AND_TARGET_STATE_IDENTICAL"); if (oldState == IComponent.ComponentState.Created) { require(newState == IComponent.ComponentState.Proposed, "ERROR:CCR-021:CREATED_INVALID_TRANSITION"); } else if (oldState == IComponent.ComponentState.Proposed) { require(newState == IComponent.ComponentState.Active || newState == IComponent.ComponentState.Declined, "ERROR:CCR-22:PROPOSED_INVALID_TRANSITION"); } else if (oldState == IComponent.ComponentState.Declined) { revert("ERROR:CCR-023:DECLINED_IS_FINAL_STATE"); } else if (oldState == IComponent.ComponentState.Active) { require(newState == IComponent.ComponentState.Paused || newState == IComponent.ComponentState.Suspended, "ERROR:CCR-024:ACTIVE_INVALID_TRANSITION"); } else if (oldState == IComponent.ComponentState.Paused) { require(newState == IComponent.ComponentState.Active || newState == IComponent.ComponentState.Archived, "ERROR:CCR-025:PAUSED_INVALID_TRANSITION"); } else if (oldState == IComponent.ComponentState.Suspended) { require(newState == IComponent.ComponentState.Active || newState == IComponent.ComponentState.Archived, "ERROR:CCR-026:SUSPENDED_INVALID_TRANSITION"); } else { revert("ERROR:CCR-027:INITIAL_STATE_NOT_HANDLED"); } } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; import "IRegistry.sol"; interface IComponent { enum ComponentType { Oracle, Product, Riskpool } enum ComponentState { Created, Proposed, Declined, Active, Paused, Suspended, Archived } event LogComponentCreated ( bytes32 componentName, IComponent.ComponentType componentType, address componentAddress, address registryAddress); function setId(uint256 id) external; function getName() external view returns(bytes32); function getId() external view returns(uint256); function getType() external view returns(ComponentType); function getState() external view returns(ComponentState); function getOwner() external view returns(address); function isProduct() external view returns(bool); function isOracle() external view returns(bool); function isRiskpool() external view returns(bool); function getRegistry() external view returns(IRegistry); function proposalCallback() external; function approvalCallback() external; function declineCallback() external; function suspendCallback() external; function resumeCallback() external; function pauseCallback() external; function unpauseCallback() external; function archiveCallback() external; }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; import "IComponent.sol"; interface IOracle is IComponent { event LogOracleCreated (address oracleAddress); event LogOracleProposed (uint256 componentId); event LogOracleApproved (uint256 componentId); event LogOracleDeclined (uint256 componentId); function request(uint256 requestId, bytes calldata input) external; function cancel(uint256 requestId) external; }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; import "IComponent.sol"; interface IProduct is IComponent { event LogProductCreated (address productAddress); event LogProductProposed (uint256 componentId); event LogProductApproved (uint256 componentId); event LogProductDeclined (uint256 componentId); function getToken() external view returns(address token); function getPolicyFlow() external view returns(address policyFlow); function getRiskpoolId() external view returns(uint256 riskpoolId); function getApplicationDataStructure() external view returns(string memory dataStructure); function getClaimDataStructure() external view returns(string memory dataStructure); function getPayoutDataStructure() external view returns(string memory dataStructure); function riskPoolCapacityCallback(uint256 capacity) external; }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; import "IComponent.sol"; import "IBundle.sol"; import "IPolicy.sol"; interface IRiskpool is IComponent { event LogRiskpoolCreated (address riskpoolAddress); event LogRiskpoolProposed (uint256 id); event LogRiskpoolApproved (uint256 id); event LogRiskpoolDeclined (uint256 id); event LogRiskpoolBundleCreated(uint256 bundleId, uint256 amount); event LogRiskpoolBundleMatchesPolicy(uint256 bundleId, bool isMatching); event LogRiskpoolCollateralLocked(bytes32 processId, uint256 collateralAmount, bool isSecured); event LogRiskpoolPremiumProcessed(bytes32 processId, uint256 amount); event LogRiskpoolPayoutProcessed(bytes32 processId, uint256 amount); event LogRiskpoolCollateralReleased(bytes32 processId, uint256 collateralAmount); function createBundle(bytes memory filter, uint256 initialAmount) external returns(uint256 bundleId); function fundBundle(uint256 bundleId, uint256 amount) external returns(uint256 netAmount); function defundBundle(uint256 bundleId, uint256 amount) external returns(uint256 netAmount); function lockBundle(uint256 bundleId) external; function unlockBundle(uint256 bundleId) external; function closeBundle(uint256 bundleId) external; function burnBundle(uint256 bundleId) external; function collateralizePolicy(bytes32 processId, uint256 collateralAmount) external returns(bool isSecured); function processPolicyPremium(bytes32 processId, uint256 amount) external; function processPolicyPayout(bytes32 processId, uint256 amount) external; function releasePolicy(bytes32 processId) external; function getCollateralizationLevel() external view returns (uint256); function getFullCollateralizationLevel() external view returns (uint256); function bundleMatchesApplication( IBundle.Bundle memory bundle, IPolicy.Application memory application ) external view returns(bool isMatching); function getFilterDataStructure() external view returns(string memory); function bundles() external view returns(uint256); function getBundle(uint256 idx) external view returns(IBundle.Bundle memory); function activeBundles() external view returns(uint256); function getActiveBundleId(uint256 idx) external view returns(uint256 bundleId); function getWallet() external view returns(address); function getErc20Token() external view returns(address); function getSumOfSumInsuredCap() external view returns (uint256); function getCapital() external view returns(uint256); function getTotalValueLocked() external view returns(uint256); function getCapacity() external view returns(uint256); function getBalance() external view returns(uint256); function setMaximumNumberOfActiveBundles(uint256 maximumNumberOfActiveBundles) external; function getMaximumNumberOfActiveBundles() external view returns(uint256 maximumNumberOfActiveBundles); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; interface IBundle { event LogBundleCreated( uint256 bundleId, uint256 riskpoolId, address owner, BundleState state, uint256 amount ); event LogBundleStateChanged(uint256 bundleId, BundleState oldState, BundleState newState); event LogBundleCapitalProvided(uint256 bundleId, address sender, uint256 amount, uint256 capacity); event LogBundleCapitalWithdrawn(uint256 bundleId, address recipient, uint256 amount, uint256 capacity); event LogBundlePolicyCollateralized(uint256 bundleId, bytes32 processId, uint256 amount, uint256 capacity); event LogBundlePayoutProcessed(uint256 bundleId, bytes32 processId, uint256 amount); event LogBundlePolicyReleased(uint256 bundleId, bytes32 processId, uint256 amount, uint256 capacity); enum BundleState { Active, Locked, Closed, Burned } struct Bundle { uint256 id; uint256 riskpoolId; uint256 tokenId; BundleState state; bytes filter; // required conditions for applications to be considered for collateralization by this bundle uint256 capital; // net investment capital amount (<= balance) uint256 lockedCapital; // capital amount linked to collateralizaion of non-closed policies (<= capital) uint256 balance; // total amount of funds: net investment capital + net premiums - payouts uint256 createdAt; uint256 updatedAt; } function create(address owner_, uint256 riskpoolId_, bytes calldata filter_, uint256 amount_) external returns(uint256 bundleId); function fund(uint256 bundleId, uint256 amount) external; function defund(uint256 bundleId, uint256 amount) external; function lock(uint256 bundleId) external; function unlock(uint256 bundleId) external; function close(uint256 bundleId) external; function burn(uint256 bundleId) external; function collateralizePolicy(uint256 bundleId, bytes32 processId, uint256 collateralAmount) external; function processPremium(uint256 bundleId, bytes32 processId, uint256 amount) external; function processPayout(uint256 bundleId, bytes32 processId, uint256 amount) external; function releasePolicy(uint256 bundleId, bytes32 processId) external returns(uint256 collateralAmount); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; interface IPolicy { // Events event LogMetadataCreated( address owner, bytes32 processId, uint256 productId, PolicyFlowState state ); event LogMetadataStateChanged( bytes32 processId, PolicyFlowState state ); event LogApplicationCreated( bytes32 processId, uint256 premiumAmount, uint256 sumInsuredAmount ); event LogApplicationRevoked(bytes32 processId); event LogApplicationUnderwritten(bytes32 processId); event LogApplicationDeclined(bytes32 processId); event LogPolicyCreated(bytes32 processId); event LogPolicyExpired(bytes32 processId); event LogPolicyClosed(bytes32 processId); event LogPremiumCollected(bytes32 processId, uint256 amount); event LogApplicationSumInsuredAdjusted(bytes32 processId, uint256 sumInsuredAmountOld, uint256 sumInsuredAmount); event LogApplicationPremiumAdjusted(bytes32 processId, uint256 premiumAmountOld, uint256 premiumAmount); event LogPolicyPremiumAdjusted(bytes32 processId, uint256 premiumExpectedAmountOld, uint256 premiumExpectedAmount); event LogClaimCreated(bytes32 processId, uint256 claimId, uint256 claimAmount); event LogClaimConfirmed(bytes32 processId, uint256 claimId, uint256 confirmedAmount); event LogClaimDeclined(bytes32 processId, uint256 claimId); event LogClaimClosed(bytes32 processId, uint256 claimId); event LogPayoutCreated( bytes32 processId, uint256 claimId, uint256 payoutId, uint256 amount ); event LogPayoutProcessed( bytes32 processId, uint256 payoutId ); // States enum PolicyFlowState {Started, Active, Finished} enum ApplicationState {Applied, Revoked, Underwritten, Declined} enum PolicyState {Active, Expired, Closed} enum ClaimState {Applied, Confirmed, Declined, Closed} enum PayoutState {Expected, PaidOut} // Objects struct Metadata { address owner; uint256 productId; PolicyFlowState state; bytes data; uint256 createdAt; uint256 updatedAt; } struct Application { ApplicationState state; uint256 premiumAmount; uint256 sumInsuredAmount; bytes data; uint256 createdAt; uint256 updatedAt; } struct Policy { PolicyState state; uint256 premiumExpectedAmount; uint256 premiumPaidAmount; uint256 claimsCount; uint256 openClaimsCount; uint256 payoutMaxAmount; uint256 payoutAmount; uint256 createdAt; uint256 updatedAt; } struct Claim { ClaimState state; uint256 claimAmount; uint256 paidAmount; bytes data; uint256 createdAt; uint256 updatedAt; } struct Payout { uint256 claimId; PayoutState state; uint256 amount; bytes data; uint256 createdAt; uint256 updatedAt; } function createPolicyFlow( address owner, uint256 productId, bytes calldata data ) external returns(bytes32 processId); function createApplication( bytes32 processId, uint256 premiumAmount, uint256 sumInsuredAmount, bytes calldata data ) external; function revokeApplication(bytes32 processId) external; function underwriteApplication(bytes32 processId) external; function declineApplication(bytes32 processId) external; function collectPremium(bytes32 processId, uint256 amount) external; function adjustPremiumSumInsured( bytes32 processId, uint256 expectedPremiumAmount, uint256 sumInsuredAmount ) external; function createPolicy(bytes32 processId) external; function expirePolicy(bytes32 processId) external; function closePolicy(bytes32 processId) external; function createClaim( bytes32 processId, uint256 claimAmount, bytes calldata data ) external returns (uint256 claimId); function confirmClaim( bytes32 processId, uint256 claimId, uint256 confirmedAmount ) external; function declineClaim(bytes32 processId, uint256 claimId) external; function closeClaim(bytes32 processId, uint256 claimId) external; function createPayout( bytes32 processId, uint256 claimId, uint256 payoutAmount, bytes calldata data ) external returns (uint256 payoutId); function processPayout( bytes32 processId, uint256 payoutId ) external; }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; import "IComponent.sol"; interface IComponentEvents { event LogComponentProposed ( bytes32 componentName, IComponent.ComponentType componentType, address componentAddress, uint256 id); event LogComponentApproved (uint256 id); event LogComponentDeclined (uint256 id); event LogComponentSuspended (uint256 id); event LogComponentResumed (uint256 id); event LogComponentPaused (uint256 id); event LogComponentUnpaused (uint256 id); event LogComponentArchived (uint256 id); event LogComponentStateChanged ( uint256 id, IComponent.ComponentState stateOld, IComponent.ComponentState stateNew); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol) pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { return _values(set._inner); } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values on the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; import "Ownable.sol"; import "ERC721.sol"; import "IBundleToken.sol"; contract BundleToken is IBundleToken, ERC721, Ownable { string public constant NAME = "GIF Bundle Token"; string public constant SYMBOL = "BTK"; mapping(uint256 /** tokenId */ => uint256 /** bundleId */) public bundleIdForTokenId; address private _bundleModule; uint256 private _totalSupply; modifier onlyBundleModule() { require(_bundleModule != address(0), "ERROR:BTK-001:NOT_INITIALIZED"); require(_msgSender() == _bundleModule, "ERROR:BTK-002:NOT_BUNDLE_MODULE"); _; } constructor() ERC721(NAME, SYMBOL) Ownable() { } function setBundleModule(address bundleModule) external { require(_bundleModule == address(0), "ERROR:BTK-003:BUNDLE_MODULE_ALREADY_DEFINED"); require(bundleModule != address(0), "ERROR:BTK-004:INVALID_BUNDLE_MODULE_ADDRESS"); _bundleModule = bundleModule; } function mint(uint256 bundleId, address to) external onlyBundleModule returns(uint256 tokenId) { _totalSupply++; tokenId = _totalSupply; bundleIdForTokenId[tokenId] = bundleId; _safeMint(to, tokenId); emit LogBundleTokenMinted(bundleId, tokenId, to); } function burn(uint256 tokenId) external onlyBundleModule { require(_exists(tokenId), "ERROR:BTK-005:TOKEN_ID_INVALID"); _burn(tokenId); emit LogBundleTokenBurned(bundleIdForTokenId[tokenId], tokenId); } function burned(uint tokenId) external override view returns(bool isBurned) { isBurned = tokenId <= _totalSupply && !_exists(tokenId); } function getBundleId(uint256 tokenId) external override view returns(uint256) { return bundleIdForTokenId[tokenId]; } function getBundleModuleAddress() external view returns(address) { return _bundleModule; } function exists(uint256 tokenId) external override view returns(bool) { return tokenId <= _totalSupply; } function totalSupply() external override view returns(uint256 tokenCount) { return _totalSupply; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "IERC721.sol"; import "IERC721Receiver.sol"; import "IERC721Metadata.sol"; import "Address.sol"; import "Context.sol"; import "Strings.sol"; import "ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _owners[tokenId]; require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner nor approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _owners[tokenId] != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ 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] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; import "IERC721.sol"; interface IBundleToken is IERC721 { event LogBundleTokenMinted(uint256 bundleId, uint256 tokenId, address tokenOwner); event LogBundleTokenBurned(uint256 bundleId, uint256 tokenId); function burned(uint tokenId) external view returns(bool isBurned); function exists(uint256 tokenId) external view returns(bool doesExist); function getBundleId(uint256 tokenId) external view returns(uint256 bundleId); function totalSupply() external view returns(uint256 tokenCount); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; import "ComponentController.sol"; import "PolicyController.sol"; import "BundleController.sol"; import "CoreController.sol"; import "IPool.sol"; import "IComponent.sol"; import "IRiskpool.sol"; import "EnumerableSet.sol"; contract PoolController is IPool, CoreController { using EnumerableSet for EnumerableSet.UintSet; // used for representation of collateralization // collateralization between 0 and 1 (1=100%) // value might be larger when overcollateralization uint256 public constant FULL_COLLATERALIZATION_LEVEL = 10**18; // upper limit for overcollateralization at 200% uint256 public constant COLLATERALIZATION_LEVEL_CAP = 2 * FULL_COLLATERALIZATION_LEVEL; uint256 public constant DEFAULT_MAX_NUMBER_OF_ACTIVE_BUNDLES = 1; mapping(bytes32 /* processId */ => uint256 /* collateralAmount*/ ) private _collateralAmount; mapping(uint256 /* productId */ => uint256 /* riskpoolId */) private _riskpoolIdForProductId; mapping(uint256 /* riskpoolId */ => IPool.Pool) private _riskpools; mapping(uint256 /* riskpoolId */ => uint256 /* maxmimumNumberOfActiveBundles */) private _maxmimumNumberOfActiveBundlesForRiskpoolId; mapping(uint256 /* riskpoolId */ => EnumerableSet.UintSet /* active bundle id set */) private _activeBundleIdsForRiskpoolId; uint256 [] private _riskpoolIds; ComponentController private _component; PolicyController private _policy; BundleController private _bundle; modifier onlyInstanceOperatorService() { require( _msgSender() == _getContractAddress("InstanceOperatorService"), "ERROR:POL-001:NOT_INSTANCE_OPERATOR" ); _; } modifier onlyRiskpoolService() { require( _msgSender() == _getContractAddress("RiskpoolService"), "ERROR:POL-002:NOT_RISKPOOL_SERVICE" ); _; } modifier onlyTreasury() { require( _msgSender() == _getContractAddress("Treasury"), "ERROR:POL-003:NOT_TREASURY" ); _; } function _afterInitialize() internal override onlyInitializing { _component = ComponentController(_getContractAddress("Component")); _policy = PolicyController(_getContractAddress("Policy")); _bundle = BundleController(_getContractAddress("Bundle")); } function registerRiskpool( uint256 riskpoolId, address wallet, address erc20Token, uint256 collateralizationLevel, uint256 sumOfSumInsuredCap ) external override onlyRiskpoolService { IPool.Pool storage pool = _riskpools[riskpoolId]; _riskpoolIds.push(riskpoolId); _maxmimumNumberOfActiveBundlesForRiskpoolId[riskpoolId] = DEFAULT_MAX_NUMBER_OF_ACTIVE_BUNDLES; require(pool.createdAt == 0, "ERROR:POL-004:RISKPOOL_ALREADY_REGISTERED"); require(wallet != address(0), "ERROR:POL-005:WALLET_ADDRESS_ZERO"); require(erc20Token != address(0), "ERROR:POL-006:ERC20_ADDRESS_ZERO"); require(collateralizationLevel <= COLLATERALIZATION_LEVEL_CAP, "ERROR:POL-007:COLLATERALIZATION_lEVEl_TOO_HIGH"); require(sumOfSumInsuredCap > 0, "ERROR:POL-008:SUM_OF_SUM_INSURED_CAP_ZERO"); pool.id = riskpoolId; pool.wallet = wallet; pool.erc20Token = erc20Token; pool.collateralizationLevel = collateralizationLevel; pool.sumOfSumInsuredCap = sumOfSumInsuredCap; pool.sumOfSumInsuredAtRisk = 0; pool.capital = 0; pool.lockedCapital = 0; pool.balance = 0; pool.createdAt = block.timestamp; pool.updatedAt = block.timestamp; emit LogRiskpoolRegistered(riskpoolId, wallet, erc20Token, collateralizationLevel, sumOfSumInsuredCap); } function setRiskpoolForProduct(uint256 productId, uint256 riskpoolId) external override onlyInstanceOperatorService { require(_component.isProduct(productId), "ERROR:POL-010:NOT_PRODUCT"); require(_component.isRiskpool(riskpoolId), "ERROR:POL-011:NOT_RISKPOOL"); require(_riskpoolIdForProductId[productId] == 0, "ERROR:POL-012:RISKPOOL_ALREADY_SET"); _riskpoolIdForProductId[productId] = riskpoolId; } function fund(uint256 riskpoolId, uint256 amount) external onlyRiskpoolService { IPool.Pool storage pool = _riskpools[riskpoolId]; pool.capital += amount; pool.balance += amount; pool.updatedAt = block.timestamp; } function defund(uint256 riskpoolId, uint256 amount) external onlyRiskpoolService { IPool.Pool storage pool = _riskpools[riskpoolId]; if (pool.capital >= amount) { pool.capital -= amount; } else { pool.capital = 0; } pool.balance -= amount; pool.updatedAt = block.timestamp; } function underwrite(bytes32 processId) external override onlyPolicyFlow("Pool") returns(bool success) { // check that application is in applied state IPolicy.Application memory application = _policy.getApplication(processId); require( application.state == IPolicy.ApplicationState.Applied, "ERROR:POL-020:APPLICATION_STATE_INVALID" ); // determine riskpool responsible for application IPolicy.Metadata memory metadata = _policy.getMetadata(processId); uint256 riskpoolId = _riskpoolIdForProductId[metadata.productId]; require( _component.getComponentState(riskpoolId) == IComponent.ComponentState.Active, "ERROR:POL-021:RISKPOOL_NOT_ACTIVE" ); // calculate required collateral amount uint256 sumInsuredAmount = application.sumInsuredAmount; uint256 collateralAmount = calculateCollateral(riskpoolId, sumInsuredAmount); _collateralAmount[processId] = collateralAmount; emit LogRiskpoolRequiredCollateral(processId, sumInsuredAmount, collateralAmount); // check that riskpool stays inside sum insured cap when underwriting this application IPool.Pool storage pool = _riskpools[riskpoolId]; require( pool.sumOfSumInsuredCap >= pool.sumOfSumInsuredAtRisk + sumInsuredAmount, "ERROR:POL-022:RISKPOOL_SUM_INSURED_CAP_EXCEEDED" ); // ask riskpool to secure application IRiskpool riskpool = _getRiskpoolComponent(metadata); success = riskpool.collateralizePolicy(processId, collateralAmount); if (success) { pool.sumOfSumInsuredAtRisk += sumInsuredAmount; pool.lockedCapital += collateralAmount; pool.updatedAt = block.timestamp; emit LogRiskpoolCollateralizationSucceeded(riskpoolId, processId, sumInsuredAmount); } else { emit LogRiskpoolCollateralizationFailed(riskpoolId, processId, sumInsuredAmount); } } function calculateCollateral(uint256 riskpoolId, uint256 sumInsuredAmount) public view returns (uint256 collateralAmount) { uint256 collateralization = getRiskpool(riskpoolId).collateralizationLevel; // fully collateralized case if (collateralization == FULL_COLLATERALIZATION_LEVEL) { collateralAmount = sumInsuredAmount; // over or under collateralized case } else if (collateralization > 0) { collateralAmount = (collateralization * sumInsuredAmount) / FULL_COLLATERALIZATION_LEVEL; } // collateralization == 0, eg complete risk coverd by re insurance outside gif else { collateralAmount = 0; } } function processPremium(bytes32 processId, uint256 amount) external override onlyPolicyFlow("Pool") { IPolicy.Metadata memory metadata = _policy.getMetadata(processId); IRiskpool riskpool = _getRiskpoolComponent(metadata); riskpool.processPolicyPremium(processId, amount); uint256 riskpoolId = _riskpoolIdForProductId[metadata.productId]; IPool.Pool storage pool = _riskpools[riskpoolId]; pool.balance += amount; pool.updatedAt = block.timestamp; } function processPayout(bytes32 processId, uint256 amount) external override onlyPolicyFlow("Pool") { IPolicy.Metadata memory metadata = _policy.getMetadata(processId); uint256 riskpoolId = _riskpoolIdForProductId[metadata.productId]; IPool.Pool storage pool = _riskpools[riskpoolId]; require(pool.createdAt > 0, "ERROR:POL-026:RISKPOOL_ID_INVALID"); require(pool.capital >= amount, "ERROR:POL-027:CAPITAL_TOO_LOW"); require(pool.lockedCapital >= amount, "ERROR:POL-028:LOCKED_CAPITAL_TOO_LOW"); require(pool.balance >= amount, "ERROR:POL-029:BALANCE_TOO_LOW"); pool.capital -= amount; pool.lockedCapital -= amount; pool.balance -= amount; pool.updatedAt = block.timestamp; // solhint-disable-line IRiskpool riskpool = _getRiskpoolComponent(metadata); riskpool.processPolicyPayout(processId, amount); } function release(bytes32 processId) external override onlyPolicyFlow("Pool") { IPolicy.Policy memory policy = _policy.getPolicy(processId); require( policy.state == IPolicy.PolicyState.Closed, "ERROR:POL-025:POLICY_STATE_INVALID" ); IPolicy.Metadata memory metadata = _policy.getMetadata(processId); IRiskpool riskpool = _getRiskpoolComponent(metadata); riskpool.releasePolicy(processId); IPolicy.Application memory application = _policy.getApplication(processId); uint256 riskpoolId = _riskpoolIdForProductId[metadata.productId]; IPool.Pool storage pool = _riskpools[riskpoolId]; uint256 remainingCollateralAmount = _collateralAmount[processId] - policy.payoutAmount; pool.sumOfSumInsuredAtRisk -= application.sumInsuredAmount; pool.lockedCapital -= remainingCollateralAmount; pool.updatedAt = block.timestamp; // solhint-disable-line // free memory delete _collateralAmount[processId]; emit LogRiskpoolCollateralReleased(riskpoolId, processId, remainingCollateralAmount); } function setMaximumNumberOfActiveBundles(uint256 riskpoolId, uint256 maxNumberOfActiveBundles) external onlyRiskpoolService { require(maxNumberOfActiveBundles > 0, "ERROR:POL-032:MAX_NUMBER_OF_ACTIVE_BUNDLES_INVALID"); _maxmimumNumberOfActiveBundlesForRiskpoolId[riskpoolId] = maxNumberOfActiveBundles; } function getMaximumNumberOfActiveBundles(uint256 riskpoolId) public view returns(uint256 maximumNumberOfActiveBundles) { return _maxmimumNumberOfActiveBundlesForRiskpoolId[riskpoolId]; } function riskpools() external view returns(uint256 idx) { return _riskpoolIds.length; } function getRiskpool(uint256 riskpoolId) public view returns(IPool.Pool memory riskPool) { riskPool = _riskpools[riskpoolId]; require(riskPool.createdAt > 0, "ERROR:POL-040:RISKPOOL_NOT_REGISTERED"); } function getRiskPoolForProduct(uint256 productId) external view returns (uint256 riskpoolId) { return _riskpoolIdForProductId[productId]; } function activeBundles(uint256 riskpoolId) external view returns(uint256 numberOfActiveBundles) { return EnumerableSet.length(_activeBundleIdsForRiskpoolId[riskpoolId]); } function getActiveBundleId(uint256 riskpoolId, uint256 bundleIdx) external view returns(uint256 bundleId) { require( bundleIdx < EnumerableSet.length(_activeBundleIdsForRiskpoolId[riskpoolId]), "ERROR:POL-041:BUNDLE_IDX_TOO_LARGE" ); return EnumerableSet.at(_activeBundleIdsForRiskpoolId[riskpoolId], bundleIdx); } function addBundleIdToActiveSet(uint256 riskpoolId, uint256 bundleId) external onlyRiskpoolService { require( !EnumerableSet.contains(_activeBundleIdsForRiskpoolId[riskpoolId], bundleId), "ERROR:POL-042:BUNDLE_ID_ALREADY_IN_SET" ); require( EnumerableSet.length(_activeBundleIdsForRiskpoolId[riskpoolId]) < _maxmimumNumberOfActiveBundlesForRiskpoolId[riskpoolId], "ERROR:POL-043:MAXIMUM_NUMBER_OF_ACTIVE_BUNDLES_REACHED" ); EnumerableSet.add(_activeBundleIdsForRiskpoolId[riskpoolId], bundleId); } function removeBundleIdFromActiveSet(uint256 riskpoolId, uint256 bundleId) external onlyRiskpoolService { require( EnumerableSet.contains(_activeBundleIdsForRiskpoolId[riskpoolId], bundleId), "ERROR:POL-044:BUNDLE_ID_NOT_IN_SET" ); EnumerableSet.remove(_activeBundleIdsForRiskpoolId[riskpoolId], bundleId); } function getFullCollateralizationLevel() external pure returns (uint256) { return FULL_COLLATERALIZATION_LEVEL; } function _getRiskpoolComponent(IPolicy.Metadata memory metadata) internal view returns (IRiskpool riskpool) { uint256 riskpoolId = _riskpoolIdForProductId[metadata.productId]; require(riskpoolId > 0, "ERROR:POL-045:RISKPOOL_DOES_NOT_EXIST"); riskpool = _getRiskpoolForId(riskpoolId); } function _getRiskpoolForId(uint256 riskpoolId) internal view returns (IRiskpool riskpool) { require(_component.isRiskpool(riskpoolId), "ERROR:POL-046:COMPONENT_NOT_RISKPOOL"); IComponent cmp = _component.getComponent(riskpoolId); riskpool = IRiskpool(address(cmp)); } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.2; interface IPool { event LogRiskpoolRegistered( uint256 riskpoolId, address wallet, address erc20Token, uint256 collateralizationLevel, uint256 sumOfSumInsuredCap ); event LogRiskpoolRequiredCollateral(bytes32 processId, uint256 sumInsured, uint256 collateral); event LogRiskpoolCollateralizationFailed(uint256 riskpoolId, bytes32 processId, uint256 amount); event LogRiskpoolCollateralizationSucceeded(uint256 riskpoolId, bytes32 processId, uint256 amount); event LogRiskpoolCollateralReleased(uint256 riskpoolId, bytes32 processId, uint256 amount); struct Pool { uint256 id; // matches component id of riskpool address wallet; // riskpool wallet address erc20Token; // the value token of the riskpool uint256 collateralizationLevel; // required collateralization level to cover new policies uint256 sumOfSumInsuredCap; // max sum of sum insured the pool is allowed to secure uint256 sumOfSumInsuredAtRisk; // current sum of sum insured at risk in this pool uint256 capital; // net investment capital amount (<= balance) uint256 lockedCapital; // capital amount linked to collateralizaion of non-closed policies (<= capital) uint256 balance; // total amount of funds: net investment capital + net premiums - payouts uint256 createdAt; uint256 updatedAt; } function registerRiskpool( uint256 riskpoolId, address wallet, address erc20Token, uint256 collateralizationLevel, uint256 sumOfSumInsuredCap ) external; function setRiskpoolForProduct(uint256 productId, uint256 riskpoolId) external; function underwrite(bytes32 processId) external returns(bool success); function processPremium(bytes32 processId, uint256 amount) external; function processPayout(bytes32 processId, uint256 amount) external; function release(bytes32 processId) external; }
{ "evmVersion": "istanbul", "optimizer": { "enabled": true, "runs": 200 }, "libraries": { "BundleController.sol": {} }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bundleId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"capacity","type":"uint256"}],"name":"LogBundleCapitalProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bundleId","type":"uint256"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"capacity","type":"uint256"}],"name":"LogBundleCapitalWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bundleId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"riskpoolId","type":"uint256"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"enum IBundle.BundleState","name":"state","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LogBundleCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bundleId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"processId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LogBundlePayoutProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bundleId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"processId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"capacity","type":"uint256"}],"name":"LogBundlePolicyCollateralized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bundleId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"processId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"capacity","type":"uint256"}],"name":"LogBundlePolicyReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bundleId","type":"uint256"},{"indexed":false,"internalType":"enum IBundle.BundleState","name":"oldState","type":"uint8"},{"indexed":false,"internalType":"enum IBundle.BundleState","name":"newState","type":"uint8"}],"name":"LogBundleStateChanged","type":"event"},{"inputs":[],"name":"bundles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"}],"name":"close","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"},{"internalType":"bytes32","name":"processId","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"collateralizePolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"uint256","name":"riskpoolId_","type":"uint256"},{"internalType":"bytes","name":"filter_","type":"bytes"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"create","outputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"defund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"fund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"}],"name":"getBundle","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"riskpoolId","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"enum IBundle.BundleState","name":"state","type":"uint8"},{"internalType":"bytes","name":"filter","type":"bytes"},{"internalType":"uint256","name":"capital","type":"uint256"},{"internalType":"uint256","name":"lockedCapital","type":"uint256"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"createdAt","type":"uint256"},{"internalType":"uint256","name":"updatedAt","type":"uint256"}],"internalType":"struct IBundle.Bundle","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"}],"name":"getCapacity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"}],"name":"getFilter","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"}],"name":"getOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"}],"name":"getState","outputs":[{"internalType":"enum IBundle.BundleState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getToken","outputs":[{"internalType":"contract BundleToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"}],"name":"getTotalValueLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"registry","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"}],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"},{"internalType":"bytes32","name":"processId","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"processPayout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"},{"internalType":"bytes32","name":"processId","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"processPremium","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"},{"internalType":"bytes32","name":"processId","type":"bytes32"}],"name":"releasePolicy","outputs":[{"internalType":"uint256","name":"remainingCollateralAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"riskpoolId","type":"uint256"}],"name":"unburntBundles","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bundleId","type":"uint256"}],"name":"unlock","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506200001c62000022565b620000e4565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff9081161015620000e2576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b612d1180620000f46000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c8063a65e2cfd116100b8578063c0e714041161007c578063c0e71404146102b6578063c397ae39146102c9578063c41a360a146102dc578063c4d66de8146102ef578063c559783e14610302578063dd4670641461032257610142565b8063a65e2cfd14610257578063b299cc261461026a578063b72674201461027d578063bb540df614610290578063bcd5349f146102a357610142565b80632d0821b71161010a5780632d0821b7146101cb5780633f5d9235146101eb57806342966c68146101fe57806344c9af28146102115780634d03f9b7146102315780636198e3391461024457610142565b80630aebeb4e1461014757806318442e631461015c5780631e0104391461017357806321df0da7146101865780632c92fb99146101ab575b600080fd5b61015a610155366004612995565b610335565b005b6008545b6040519081526020015b60405180910390f35b610160610181366004612995565b610405565b6003546001600160a01b03165b6040516001600160a01b03909116815260200161016a565b6101be6101b9366004612995565b61041c565b60405161016a9190612a5f565b6101de6101d9366004612995565b610431565b60405161016a9190612ac2565b6101606101f9366004612995565b6105ed565b61015a61020c366004612995565b610602565b61022461021f366004612995565b6107ba565b60405161016a9190612a72565b61015a61023f3660046129e6565b6107cf565b61015a610252366004612995565b610c1d565b61015a6102653660046129c5565b610c73565b61015a6102783660046129e6565b610e4a565b61015a61028b3660046129e6565b611374565b61016061029e3660046129c5565b611672565b6101606102b1366004612995565b6119d6565b6101606102c43660046127d4565b6119ff565b61015a6102d73660046129c5565b611c28565b6101936102ea366004612995565b611e00565b61015a6102fd36600461279c565b611e90565b610160610310366004612995565b60009081526007602052604090205490565b61015a610330366004612995565b61200d565b6103506e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b0316146103895760405162461bcd60e51b815260040161038090612a80565b60405180910390fd5b600081815260056020526040902054156103f75760405162461bcd60e51b815260206004820152602960248201527f4552524f523a4255432d3031353a42554e444c455f574954485f4143544956456044820152685f504f4c494349455360b81b6064820152608401610380565b61040281600261214b565b50565b600061041082610431565b60e0015190505b919050565b606061042782610431565b6080015192915050565b610439612618565b600082815260046020908152604080832081516101408101835281548152600182015493810193909352600281015491830191909152600380820154606084019160ff9091169081111561049d57634e487b7160e01b600052602160045260246000fd5b60038111156104bc57634e487b7160e01b600052602160045260246000fd5b81526020016004820180546104d090612c44565b80601f01602080910402602001604051908101604052809291908181526020018280546104fc90612c44565b80156105495780601f1061051e57610100808354040283529160200191610549565b820191906000526020600020905b81548152906001019060200180831161052c57829003601f168201915b505050505081526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152505090506000816101000151116105e75760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3036303a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b92915050565b60006105f882610431565b60c0015192915050565b61061d6e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b03161461064d5760405162461bcd60e51b815260040161038090612a80565b6000818152600460205260409020600260038083015460ff169081111561068457634e487b7160e01b600052602160045260246000fd5b146106d15760405162461bcd60e51b815260206004820152601f60248201527f4552524f523a4255432d3031363a42554e444c455f4e4f545f434c4f534544006044820152606401610380565b6007810154156107235760405162461bcd60e51b815260206004820181905260248201527f4552524f523a4255432d3031373a42554e444c455f4841535f42414c414e43456044820152606401610380565b600354604051630852cd8d60e31b8152600481018490526001600160a01b03909116906342966c6890602401600060405180830381600087803b15801561076957600080fd5b505af115801561077d573d6000803e3d6000fd5b50505050600181810154600090815260076020526040812080549091906107a5908490612bfd565b909155506107b6905082600361214b565b5050565b60006107c582610431565b6060015192915050565b6107ea6e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b03161461081a5760405162461bcd60e51b815260040161038090612a80565b60025460405163296586d360e21b8152600481018490526000916001600160a01b03169063a5961b4c9060240160006040518083038186803b15801561085f57600080fd5b505afa158015610873573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261089b9190810190612860565b60008581526004602052604090209091506108b46121ac565b6001600160a01b031663d229f3b083602001516040518263ffffffff1660e01b81526004016108e591815260200190565b60206040518083038186803b1580156108fd57600080fd5b505afa158015610911573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093591906129ad565b8160010154146109935760405162461bcd60e51b8152602060048201526024808201527f4552524f523a4255432d3031393a42554e444c455f4e4f545f494e5f5249534b6044820152631413d3d360e21b6064820152608401610380565b60008160080154116109f35760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3032303a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b600060038083015460ff1690811115610a1c57634e487b7160e01b600052602160045260246000fd5b14610a695760405162461bcd60e51b815260206004820152601f60248201527f4552524f523a4255432d3032313a42554e444c455f4e4f545f414354495645006044820152606401610380565b828160060154610a799190612be5565b81600501541015610acc5760405162461bcd60e51b815260206004820152601e60248201527f4552524f523a4255432d3032323a43415041434954595f544f4f5f4c4f5700006044820152606401610380565b600085815260066020908152604080832087845290915290205415610b595760405162461bcd60e51b815260206004820152603b60248201527f4552524f523a4255432d3032333a494e4352454d454e54414c5f434f4c4c415460448201527f4552414c495a4154494f4e5f4e4f545f494d504c454d454e54454400000000006064820152608401610380565b82816006016000828254610b6d9190612be5565b90915550504260098201556000858152600560205260408120805460019290610b97908490612be5565b9091555050600085815260066020818152604080842088855290915282208590558201546005830154610bca9190612bfd565b6040805188815260208101889052908101869052606081018290529091507fb253c82cbaad89e2bd0fb78bc565243ccc06da1ac58b640ed94469f69b64ea549060800160405180910390a1505050505050565b610c386e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b031614610c685760405162461bcd60e51b815260040161038090612a80565b61040281600061214b565b610c8e6e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b031614610cbe5760405162461bcd60e51b815260040161038090612a80565b60008281526004602052604090206008810154610d295760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3031313a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b600260038083015460ff1690811115610d5257634e487b7160e01b600052602160045260246000fd5b1415610da05760405162461bcd60e51b815260206004820152601b60248201527f4552524f523a4255432d3031323a42554e444c455f434c4f53454400000000006044820152606401610380565b81816005016000828254610db49190612be5565b9250508190555081816007016000828254610dcf9190612be5565b909155505042600982015560068101546005820154600091610df091612bfd565b90507fed746f45e63100861a9a492e092018cdce2d2645b83741099a6f8ecba2af013884335b604080519283526001600160a01b03909116602083015281018590526060810183905260800160405180910390a150505050565b610e656e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b031614610e955760405162461bcd60e51b815260040161038090612a80565b60025460405163a3f685f960e01b8152600481018490526000916001600160a01b03169063a3f685f9906024016101206040518083038186803b158015610edb57600080fd5b505afa158015610eef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f139190612910565b9050600281516002811115610f3857634e487b7160e01b600052602160045260246000fd5b1415610f915760405162461bcd60e51b815260206004820152602260248201527f4552524f523a504f4c2d3034303a504f4c4943595f53544154455f494e56414c604482015261125160f21b6064820152608401610380565b6000848152600560205260409020546110005760405162461bcd60e51b815260206004820152602b60248201527f4552524f523a4255432d3034313a4e4f5f4143544956455f504f4c494349455360448201526a5f464f525f42554e444c4560a81b6064820152608401610380565b60008481526006602090815260408083208684529091529020548211156110825760405162461bcd60e51b815260206004820152603060248201527f4552524f523a4255432d3034323a434f4c4c41544552414c5f494e535546464960448201526f4349454e545f464f525f504f4c49435960801b6064820152608401610380565b600084815260046020526040902060088101546110ed5760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3034333a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b600060038083015460ff169081111561111657634e487b7160e01b600052602160045260246000fd5b14806111485750600160038083015460ff169081111561114657634e487b7160e01b600052602160045260246000fd5b145b61119f5760405162461bcd60e51b815260206004820152602260248201527f4552524f523a4255432d3034343a42554e444c455f53544154455f494e56414c604482015261125160f21b6064820152608401610380565b82816005015410156111f35760405162461bcd60e51b815260206004820152601d60248201527f4552524f523a4255432d3034353a4341504954414c5f544f4f5f4c4f570000006044820152606401610380565b82816006015410156112535760405162461bcd60e51b8152602060048201526024808201527f4552524f523a4255432d3034363a4c4f434b45445f4341504954414c5f544f4f6044820152635f4c4f5760e01b6064820152608401610380565b82816007015410156112a75760405162461bcd60e51b815260206004820152601d60248201527f4552524f523a4255432d3034373a42414c414e43455f544f4f5f4c4f570000006044820152606401610380565b6000858152600660209081526040808320878452909152812080548592906112d0908490612bfd565b92505081905550828160050160008282546112eb9190612bfd565b92505081905550828160060160008282546113069190612bfd565b92505081905550828160070160008282546113219190612bfd565b909155505042600982015560408051868152602081018690529081018490527f34ea3fe7b8e6aa959a187f606dc076e9fb02379d613a2c9356f5a556aac9508c9060600160405180910390a15050505050565b61138f6e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b0316146113bf5760405162461bcd60e51b815260040161038090612a80565b6000838152600460205260409020600881015484919061142d5760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3030323a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b60038181015460ff168181111561145457634e487b7160e01b600052602160045260246000fd5b141580156114895750600260038083015460ff169081111561148657634e487b7160e01b600052602160045260246000fd5b14155b6114e35760405162461bcd60e51b815260206004820152602560248201527f4552524f523a4255432d3030333a42554e444c455f4255524e45445f4f525f436044820152641313d4d15160da1b6064820152608401610380565b60025460405163a3f685f960e01b8152600481018690526000916001600160a01b03169063a3f685f9906024016101206040518083038186803b15801561152957600080fd5b505afa15801561153d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115619190612910565b905060028151600281111561158657634e487b7160e01b600052602160045260246000fd5b14156115df5760405162461bcd60e51b815260206004820152602260248201527f4552524f523a504f4c2d3033303a504f4c4943595f53544154455f494e56414c604482015261125160f21b6064820152608401610380565b6000868152600460205260409020600881015461164a5760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3033313a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b8481600701600082825461165e9190612be5565b909155505042600990910155505050505050565b600061168f6e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b0316146116bf5760405162461bcd60e51b815260040161038090612a80565b60025460405163a3f685f960e01b8152600481018490526000916001600160a01b03169063a3f685f9906024016101206040518083038186803b15801561170557600080fd5b505afa158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190612910565b905060028151600281111561176257634e487b7160e01b600052602160045260246000fd5b146117ba5760405162461bcd60e51b815260206004820152602260248201527f4552524f523a504f4c2d3035303a504f4c4943595f53544154455f494e56414c604482015261125160f21b6064820152608401610380565b600084815260046020526040902060088101546118255760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3035313a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b6000858152600560205260409020546118945760405162461bcd60e51b815260206004820152602b60248201527f4552524f523a4255432d3035323a4e4f5f4143544956455f504f4c494349455360448201526a5f464f525f42554e444c4560a81b6064820152608401610380565b6000858152600660208181526040808420888552909152909120549082015481111561190e5760405162461bcd60e51b8152602060048201526024808201527f50414e49433a4255432d3035333a554e4c4f434b5f4341504954414c5f544f4f6044820152635f42494760e01b6064820152608401610380565b600086815260056020526040812080546001929061192d908490612bfd565b90915550506000868152600660208181526040808420898552909152822082905583018054839290611960908490612bfd565b90915550504260098301556006820154600583015460009161198191612bfd565b6040805189815260208101899052908101849052606081018290529091507fa7edca0329e0f25a5a213baaa606802692de7155da4cf8a007aedf326d9180759060800160405180910390a15050505092915050565b6000806119e283610431565b90508060c001518160a001516119f89190612bfd565b9392505050565b6000611a1c6e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b031614611a4c5760405162461bcd60e51b815260040161038090612a80565b600854611a5a906001612be5565b600081815260046020526040902060088101549192509015611aca5760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3031303a42554e444c455f414c52454144595f45584960448201526253545360e81b6064820152608401610380565b6003546040516394bf804d60e01b8152600481018490526001600160a01b03898116602483015260009216906394bf804d90604401602060405180830381600087803b158015611b1957600080fd5b505af1158015611b2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5191906129ad565b838355600283018190556001830188905560038301805460ff191690559050611b7e60048301878761268a565b50600582018490556007820184905542600880840182905560098401919091558054906000611bac83612c7f565b90915550506000878152600760205260408120805491611bcb83612c7f565b90915550508154600383015460058401546040517f2a6ff62099c2d2515017f639043aef82d6293361b7cb7bdc90854eb2f026b56c93611c159390928c928e9260ff169190612b7a565b60405180910390a1505095945050505050565b611c436e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b031614611c735760405162461bcd60e51b815260040161038090612a80565b60008281526004602052604090206008810154611cde5760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3031333a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b818160060154611cee9190612be5565b8160050154101580611d1157506006810154158015611d11575081816007015410155b611d6f5760405162461bcd60e51b815260206004820152602960248201527f4552524f523a4255432d3031343a43415041434954595f4f525f42414c414e43604482015268455f544f4f5f4c4f5760b81b6064820152608401610380565b81816005015410611d995781816005016000828254611d8e9190612bfd565b90915550611da19050565b600060058201555b81816007016000828254611db59190612bfd565b909155505042600982015560068101546005820154600091611dd691612bfd565b90507fe3d161947307a0d06b7ac0f3a183176acbc70afff0831bba7e694ef9f47323bd8433610e16565b600080611e0c83610431565b60409081015160035491516331a9108f60e11b8152600481018290529092506001600160a01b0390911690636352211e9060240160206040518083038186803b158015611e5857600080fd5b505afa158015611e6c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f891906127b8565b600054610100900460ff1615808015611eb05750600054600160ff909116105b80611eca5750303b158015611eca575060005460ff166001145b611f2d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610380565b6000805460ff191660011790558015611f50576000805461ff0019166101001790555b6000805462010000600160b01b031916620100006001600160a01b03851602179055611f7a600090565b6541636365737360d01b14611fbc57611f9b6541636365737360d01b612063565b600180546001600160a01b0319166001600160a01b03929092169190911790555b611fc46121c3565b80156107b6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6120286e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b0316146120585760405162461bcd60e51b815260040161038090612a80565b61040281600161214b565b60008054604051631c2d8fb360e31b815260048101849052620100009091046001600160a01b03169063e16c7d989060240160206040518083038186803b1580156120ad57600080fd5b505afa1580156120c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e591906127b8565b90506001600160a01b0381166104175760405162461bcd60e51b815260206004820152602560248201527f4552524f523a4352432d3030343a434f4e54524143545f4e4f545f5245474953604482015264151154915160da1b6064820152608401610380565b6000612156836107ba565b90506121628183612299565b61216c83836125bb565b7f0c318b62e2d75a1d66c8fa6d64604f76f84b646cf3dadfb56e336044d57061f583828460405161219f93929190612b59565b60405180910390a1505050565b60006121be63141bdbdb60e21b612063565b905090565b600054610100900460ff1661222e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610380565b61224065506f6c69637960d01b612063565b600280546001600160a01b0319166001600160a01b03929092169190911790556122776a213ab7323632aa37b5b2b760a91b612063565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60008260038111156122bb57634e487b7160e01b600052602160045260246000fd5b141561236f5760018160038111156122e357634e487b7160e01b600052602160045260246000fd5b148061230e5750600281600381111561230c57634e487b7160e01b600052602160045260246000fd5b145b61236a5760405162461bcd60e51b815260206004820152602760248201527f4552524f523a4255432d3037303a4143544956455f494e56414c49445f5452416044820152662729a4aa24a7a760c91b6064820152608401610380565b6107b6565b600182600381111561239157634e487b7160e01b600052602160045260246000fd5b14156124405760008160038111156123b957634e487b7160e01b600052602160045260246000fd5b14806123e4575060028160038111156123e257634e487b7160e01b600052602160045260246000fd5b145b61236a5760405162461bcd60e51b815260206004820152602760248201527f4552524f523a4255432d3037313a4c4f434b45445f494e56414c49445f5452416044820152662729a4aa24a7a760c91b6064820152608401610380565b600282600381111561246257634e487b7160e01b600052602160045260246000fd5b14156124e757600381600381111561248a57634e487b7160e01b600052602160045260246000fd5b1461236a5760405162461bcd60e51b815260206004820152602760248201527f4552524f523a4255432d3037323a434c4f5345445f494e56414c49445f5452416044820152662729a4aa24a7a760c91b6064820152608401610380565b600382600381111561250957634e487b7160e01b600052602160045260246000fd5b14156125635760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3037333a4255524e45445f49535f46494e414c5f535460448201526241544560e81b6064820152608401610380565b60405162461bcd60e51b815260206004820152602760248201527f4552524f523a424f432d3037343a494e495449414c5f53544154455f4e4f545f6044820152661210539113115160ca1b6064820152608401610380565b600082815260046020526040902060039081018054839260ff199091169060019084908111156125fb57634e487b7160e01b600052602160045260246000fd5b021790555050600090815260046020526040902042600990910155565b6040518061014001604052806000815260200160008152602001600081526020016000600381111561265a57634e487b7160e01b600052602160045260246000fd5b81526020016060815260200160008152602001600081526020016000815260200160008152602001600081525090565b82805461269690612c44565b90600052602060002090601f0160209004810192826126b857600085556126fe565b82601f106126d15782800160ff198235161785556126fe565b828001600101855582156126fe579182015b828111156126fe5782358255916020019190600101906126e3565b5061270a92915061270e565b5090565b5b8082111561270a576000815560010161270f565b600082601f830112612733578081fd5b815167ffffffffffffffff81111561274d5761274d612cb0565b612760601f8201601f1916602001612bb4565b818152846020838601011115612774578283fd5b612785826020830160208701612c14565b949350505050565b80516003811061041757600080fd5b6000602082840312156127ad578081fd5b81356119f881612cc6565b6000602082840312156127c9578081fd5b81516119f881612cc6565b6000806000806000608086880312156127eb578081fd5b85356127f681612cc6565b945060208601359350604086013567ffffffffffffffff80821115612819578283fd5b818801915088601f83011261282c578283fd5b81358181111561283a578384fd5b89602082850101111561284b578384fd5b96999598505060200195606001359392505050565b600060208284031215612871578081fd5b815167ffffffffffffffff80821115612888578283fd5b9083019060c0828603121561289b578283fd5b6128a560c0612bb4565b82516128b081612cc6565b8152602083810151908201526128c86040840161278d565b60408201526060830151828111156128de578485fd5b6128ea87828601612723565b6060830152506080830151608082015260a083015160a082015280935050505092915050565b6000610120808385031215612923578182fd5b61292c81612bb4565b90506129378361278d565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b6000602082840312156129a6578081fd5b5035919050565b6000602082840312156129be578081fd5b5051919050565b600080604083850312156129d7578182fd5b50508035926020909101359150565b6000806000606084860312156129fa578283fd5b505081359360208301359350604090920135919050565b60008151808452612a29816020860160208601612c14565b601f01601f19169290920160200192915050565b60048110612a5b57634e487b7160e01b600052602160045260246000fd5b9052565b6000602082526119f86020830184612a11565b602081016105e78284612a3d565b60208082526022908201527f4552524f523a4255432d3030313a4e4f545f5249534b504f4f4c5f5345525649604082015261434560f01b606082015260800190565b6000602082528251602083015260208301516040830152604083015160608301526060830151612af56080840182612a3d565b5060808301516101408060a0850152612b12610160850183612a11565b915060a085015160c085015260c085015160e085015260e0850151610100818187015280870151915050610120818187015280870151838701525050508091505092915050565b83815260608101612b6d6020830185612a3d565b6127856040830184612a3d565b858152602081018590526001600160a01b038416604082015260a08101612ba46060830185612a3d565b8260808301529695505050505050565b604051601f8201601f1916810167ffffffffffffffff81118282101715612bdd57612bdd612cb0565b604052919050565b60008219821115612bf857612bf8612c9a565b500190565b600082821015612c0f57612c0f612c9a565b500390565b60005b83811015612c2f578181015183820152602001612c17565b83811115612c3e576000848401525b50505050565b600281046001821680612c5857607f821691505b60208210811415612c7957634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415612c9357612c93612c9a565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461040257600080fdfea26469706673582212202c90c44b09882a110500aeecf0b77d6a868254581f199a70003d75b9227e578a64736f6c63430008020033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101425760003560e01c8063a65e2cfd116100b8578063c0e714041161007c578063c0e71404146102b6578063c397ae39146102c9578063c41a360a146102dc578063c4d66de8146102ef578063c559783e14610302578063dd4670641461032257610142565b8063a65e2cfd14610257578063b299cc261461026a578063b72674201461027d578063bb540df614610290578063bcd5349f146102a357610142565b80632d0821b71161010a5780632d0821b7146101cb5780633f5d9235146101eb57806342966c68146101fe57806344c9af28146102115780634d03f9b7146102315780636198e3391461024457610142565b80630aebeb4e1461014757806318442e631461015c5780631e0104391461017357806321df0da7146101865780632c92fb99146101ab575b600080fd5b61015a610155366004612995565b610335565b005b6008545b6040519081526020015b60405180910390f35b610160610181366004612995565b610405565b6003546001600160a01b03165b6040516001600160a01b03909116815260200161016a565b6101be6101b9366004612995565b61041c565b60405161016a9190612a5f565b6101de6101d9366004612995565b610431565b60405161016a9190612ac2565b6101606101f9366004612995565b6105ed565b61015a61020c366004612995565b610602565b61022461021f366004612995565b6107ba565b60405161016a9190612a72565b61015a61023f3660046129e6565b6107cf565b61015a610252366004612995565b610c1d565b61015a6102653660046129c5565b610c73565b61015a6102783660046129e6565b610e4a565b61015a61028b3660046129e6565b611374565b61016061029e3660046129c5565b611672565b6101606102b1366004612995565b6119d6565b6101606102c43660046127d4565b6119ff565b61015a6102d73660046129c5565b611c28565b6101936102ea366004612995565b611e00565b61015a6102fd36600461279c565b611e90565b610160610310366004612995565b60009081526007602052604090205490565b61015a610330366004612995565b61200d565b6103506e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b0316146103895760405162461bcd60e51b815260040161038090612a80565b60405180910390fd5b600081815260056020526040902054156103f75760405162461bcd60e51b815260206004820152602960248201527f4552524f523a4255432d3031353a42554e444c455f574954485f4143544956456044820152685f504f4c494349455360b81b6064820152608401610380565b61040281600261214b565b50565b600061041082610431565b60e0015190505b919050565b606061042782610431565b6080015192915050565b610439612618565b600082815260046020908152604080832081516101408101835281548152600182015493810193909352600281015491830191909152600380820154606084019160ff9091169081111561049d57634e487b7160e01b600052602160045260246000fd5b60038111156104bc57634e487b7160e01b600052602160045260246000fd5b81526020016004820180546104d090612c44565b80601f01602080910402602001604051908101604052809291908181526020018280546104fc90612c44565b80156105495780601f1061051e57610100808354040283529160200191610549565b820191906000526020600020905b81548152906001019060200180831161052c57829003601f168201915b505050505081526020016005820154815260200160068201548152602001600782015481526020016008820154815260200160098201548152505090506000816101000151116105e75760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3036303a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b92915050565b60006105f882610431565b60c0015192915050565b61061d6e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b03161461064d5760405162461bcd60e51b815260040161038090612a80565b6000818152600460205260409020600260038083015460ff169081111561068457634e487b7160e01b600052602160045260246000fd5b146106d15760405162461bcd60e51b815260206004820152601f60248201527f4552524f523a4255432d3031363a42554e444c455f4e4f545f434c4f534544006044820152606401610380565b6007810154156107235760405162461bcd60e51b815260206004820181905260248201527f4552524f523a4255432d3031373a42554e444c455f4841535f42414c414e43456044820152606401610380565b600354604051630852cd8d60e31b8152600481018490526001600160a01b03909116906342966c6890602401600060405180830381600087803b15801561076957600080fd5b505af115801561077d573d6000803e3d6000fd5b50505050600181810154600090815260076020526040812080549091906107a5908490612bfd565b909155506107b6905082600361214b565b5050565b60006107c582610431565b6060015192915050565b6107ea6e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b03161461081a5760405162461bcd60e51b815260040161038090612a80565b60025460405163296586d360e21b8152600481018490526000916001600160a01b03169063a5961b4c9060240160006040518083038186803b15801561085f57600080fd5b505afa158015610873573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261089b9190810190612860565b60008581526004602052604090209091506108b46121ac565b6001600160a01b031663d229f3b083602001516040518263ffffffff1660e01b81526004016108e591815260200190565b60206040518083038186803b1580156108fd57600080fd5b505afa158015610911573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061093591906129ad565b8160010154146109935760405162461bcd60e51b8152602060048201526024808201527f4552524f523a4255432d3031393a42554e444c455f4e4f545f494e5f5249534b6044820152631413d3d360e21b6064820152608401610380565b60008160080154116109f35760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3032303a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b600060038083015460ff1690811115610a1c57634e487b7160e01b600052602160045260246000fd5b14610a695760405162461bcd60e51b815260206004820152601f60248201527f4552524f523a4255432d3032313a42554e444c455f4e4f545f414354495645006044820152606401610380565b828160060154610a799190612be5565b81600501541015610acc5760405162461bcd60e51b815260206004820152601e60248201527f4552524f523a4255432d3032323a43415041434954595f544f4f5f4c4f5700006044820152606401610380565b600085815260066020908152604080832087845290915290205415610b595760405162461bcd60e51b815260206004820152603b60248201527f4552524f523a4255432d3032333a494e4352454d454e54414c5f434f4c4c415460448201527f4552414c495a4154494f4e5f4e4f545f494d504c454d454e54454400000000006064820152608401610380565b82816006016000828254610b6d9190612be5565b90915550504260098201556000858152600560205260408120805460019290610b97908490612be5565b9091555050600085815260066020818152604080842088855290915282208590558201546005830154610bca9190612bfd565b6040805188815260208101889052908101869052606081018290529091507fb253c82cbaad89e2bd0fb78bc565243ccc06da1ac58b640ed94469f69b64ea549060800160405180910390a1505050505050565b610c386e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b031614610c685760405162461bcd60e51b815260040161038090612a80565b61040281600061214b565b610c8e6e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b031614610cbe5760405162461bcd60e51b815260040161038090612a80565b60008281526004602052604090206008810154610d295760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3031313a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b600260038083015460ff1690811115610d5257634e487b7160e01b600052602160045260246000fd5b1415610da05760405162461bcd60e51b815260206004820152601b60248201527f4552524f523a4255432d3031323a42554e444c455f434c4f53454400000000006044820152606401610380565b81816005016000828254610db49190612be5565b9250508190555081816007016000828254610dcf9190612be5565b909155505042600982015560068101546005820154600091610df091612bfd565b90507fed746f45e63100861a9a492e092018cdce2d2645b83741099a6f8ecba2af013884335b604080519283526001600160a01b03909116602083015281018590526060810183905260800160405180910390a150505050565b610e656e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b031614610e955760405162461bcd60e51b815260040161038090612a80565b60025460405163a3f685f960e01b8152600481018490526000916001600160a01b03169063a3f685f9906024016101206040518083038186803b158015610edb57600080fd5b505afa158015610eef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f139190612910565b9050600281516002811115610f3857634e487b7160e01b600052602160045260246000fd5b1415610f915760405162461bcd60e51b815260206004820152602260248201527f4552524f523a504f4c2d3034303a504f4c4943595f53544154455f494e56414c604482015261125160f21b6064820152608401610380565b6000848152600560205260409020546110005760405162461bcd60e51b815260206004820152602b60248201527f4552524f523a4255432d3034313a4e4f5f4143544956455f504f4c494349455360448201526a5f464f525f42554e444c4560a81b6064820152608401610380565b60008481526006602090815260408083208684529091529020548211156110825760405162461bcd60e51b815260206004820152603060248201527f4552524f523a4255432d3034323a434f4c4c41544552414c5f494e535546464960448201526f4349454e545f464f525f504f4c49435960801b6064820152608401610380565b600084815260046020526040902060088101546110ed5760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3034333a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b600060038083015460ff169081111561111657634e487b7160e01b600052602160045260246000fd5b14806111485750600160038083015460ff169081111561114657634e487b7160e01b600052602160045260246000fd5b145b61119f5760405162461bcd60e51b815260206004820152602260248201527f4552524f523a4255432d3034343a42554e444c455f53544154455f494e56414c604482015261125160f21b6064820152608401610380565b82816005015410156111f35760405162461bcd60e51b815260206004820152601d60248201527f4552524f523a4255432d3034353a4341504954414c5f544f4f5f4c4f570000006044820152606401610380565b82816006015410156112535760405162461bcd60e51b8152602060048201526024808201527f4552524f523a4255432d3034363a4c4f434b45445f4341504954414c5f544f4f6044820152635f4c4f5760e01b6064820152608401610380565b82816007015410156112a75760405162461bcd60e51b815260206004820152601d60248201527f4552524f523a4255432d3034373a42414c414e43455f544f4f5f4c4f570000006044820152606401610380565b6000858152600660209081526040808320878452909152812080548592906112d0908490612bfd565b92505081905550828160050160008282546112eb9190612bfd565b92505081905550828160060160008282546113069190612bfd565b92505081905550828160070160008282546113219190612bfd565b909155505042600982015560408051868152602081018690529081018490527f34ea3fe7b8e6aa959a187f606dc076e9fb02379d613a2c9356f5a556aac9508c9060600160405180910390a15050505050565b61138f6e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b0316146113bf5760405162461bcd60e51b815260040161038090612a80565b6000838152600460205260409020600881015484919061142d5760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3030323a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b60038181015460ff168181111561145457634e487b7160e01b600052602160045260246000fd5b141580156114895750600260038083015460ff169081111561148657634e487b7160e01b600052602160045260246000fd5b14155b6114e35760405162461bcd60e51b815260206004820152602560248201527f4552524f523a4255432d3030333a42554e444c455f4255524e45445f4f525f436044820152641313d4d15160da1b6064820152608401610380565b60025460405163a3f685f960e01b8152600481018690526000916001600160a01b03169063a3f685f9906024016101206040518083038186803b15801561152957600080fd5b505afa15801561153d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115619190612910565b905060028151600281111561158657634e487b7160e01b600052602160045260246000fd5b14156115df5760405162461bcd60e51b815260206004820152602260248201527f4552524f523a504f4c2d3033303a504f4c4943595f53544154455f494e56414c604482015261125160f21b6064820152608401610380565b6000868152600460205260409020600881015461164a5760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3033313a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b8481600701600082825461165e9190612be5565b909155505042600990910155505050505050565b600061168f6e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b0316146116bf5760405162461bcd60e51b815260040161038090612a80565b60025460405163a3f685f960e01b8152600481018490526000916001600160a01b03169063a3f685f9906024016101206040518083038186803b15801561170557600080fd5b505afa158015611719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173d9190612910565b905060028151600281111561176257634e487b7160e01b600052602160045260246000fd5b146117ba5760405162461bcd60e51b815260206004820152602260248201527f4552524f523a504f4c2d3035303a504f4c4943595f53544154455f494e56414c604482015261125160f21b6064820152608401610380565b600084815260046020526040902060088101546118255760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3035313a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b6000858152600560205260409020546118945760405162461bcd60e51b815260206004820152602b60248201527f4552524f523a4255432d3035323a4e4f5f4143544956455f504f4c494349455360448201526a5f464f525f42554e444c4560a81b6064820152608401610380565b6000858152600660208181526040808420888552909152909120549082015481111561190e5760405162461bcd60e51b8152602060048201526024808201527f50414e49433a4255432d3035333a554e4c4f434b5f4341504954414c5f544f4f6044820152635f42494760e01b6064820152608401610380565b600086815260056020526040812080546001929061192d908490612bfd565b90915550506000868152600660208181526040808420898552909152822082905583018054839290611960908490612bfd565b90915550504260098301556006820154600583015460009161198191612bfd565b6040805189815260208101899052908101849052606081018290529091507fa7edca0329e0f25a5a213baaa606802692de7155da4cf8a007aedf326d9180759060800160405180910390a15050505092915050565b6000806119e283610431565b90508060c001518160a001516119f89190612bfd565b9392505050565b6000611a1c6e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b031614611a4c5760405162461bcd60e51b815260040161038090612a80565b600854611a5a906001612be5565b600081815260046020526040902060088101549192509015611aca5760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3031303a42554e444c455f414c52454144595f45584960448201526253545360e81b6064820152608401610380565b6003546040516394bf804d60e01b8152600481018490526001600160a01b03898116602483015260009216906394bf804d90604401602060405180830381600087803b158015611b1957600080fd5b505af1158015611b2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5191906129ad565b838355600283018190556001830188905560038301805460ff191690559050611b7e60048301878761268a565b50600582018490556007820184905542600880840182905560098401919091558054906000611bac83612c7f565b90915550506000878152600760205260408120805491611bcb83612c7f565b90915550508154600383015460058401546040517f2a6ff62099c2d2515017f639043aef82d6293361b7cb7bdc90854eb2f026b56c93611c159390928c928e9260ff169190612b7a565b60405180910390a1505095945050505050565b611c436e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b031614611c735760405162461bcd60e51b815260040161038090612a80565b60008281526004602052604090206008810154611cde5760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3031333a42554e444c455f444f45535f4e4f545f45586044820152621254d560ea1b6064820152608401610380565b818160060154611cee9190612be5565b8160050154101580611d1157506006810154158015611d11575081816007015410155b611d6f5760405162461bcd60e51b815260206004820152602960248201527f4552524f523a4255432d3031343a43415041434954595f4f525f42414c414e43604482015268455f544f4f5f4c4f5760b81b6064820152608401610380565b81816005015410611d995781816005016000828254611d8e9190612bfd565b90915550611da19050565b600060058201555b81816007016000828254611db59190612bfd565b909155505042600982015560068101546005820154600091611dd691612bfd565b90507fe3d161947307a0d06b7ac0f3a183176acbc70afff0831bba7e694ef9f47323bd8433610e16565b600080611e0c83610431565b60409081015160035491516331a9108f60e11b8152600481018290529092506001600160a01b0390911690636352211e9060240160206040518083038186803b158015611e5857600080fd5b505afa158015611e6c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f891906127b8565b600054610100900460ff1615808015611eb05750600054600160ff909116105b80611eca5750303b158015611eca575060005460ff166001145b611f2d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610380565b6000805460ff191660011790558015611f50576000805461ff0019166101001790555b6000805462010000600160b01b031916620100006001600160a01b03851602179055611f7a600090565b6541636365737360d01b14611fbc57611f9b6541636365737360d01b612063565b600180546001600160a01b0319166001600160a01b03929092169190911790555b611fc46121c3565b80156107b6576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6120286e5269736b706f6f6c5365727669636560881b612063565b6001600160a01b0316336001600160a01b0316146120585760405162461bcd60e51b815260040161038090612a80565b61040281600161214b565b60008054604051631c2d8fb360e31b815260048101849052620100009091046001600160a01b03169063e16c7d989060240160206040518083038186803b1580156120ad57600080fd5b505afa1580156120c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e591906127b8565b90506001600160a01b0381166104175760405162461bcd60e51b815260206004820152602560248201527f4552524f523a4352432d3030343a434f4e54524143545f4e4f545f5245474953604482015264151154915160da1b6064820152608401610380565b6000612156836107ba565b90506121628183612299565b61216c83836125bb565b7f0c318b62e2d75a1d66c8fa6d64604f76f84b646cf3dadfb56e336044d57061f583828460405161219f93929190612b59565b60405180910390a1505050565b60006121be63141bdbdb60e21b612063565b905090565b600054610100900460ff1661222e5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401610380565b61224065506f6c69637960d01b612063565b600280546001600160a01b0319166001600160a01b03929092169190911790556122776a213ab7323632aa37b5b2b760a91b612063565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60008260038111156122bb57634e487b7160e01b600052602160045260246000fd5b141561236f5760018160038111156122e357634e487b7160e01b600052602160045260246000fd5b148061230e5750600281600381111561230c57634e487b7160e01b600052602160045260246000fd5b145b61236a5760405162461bcd60e51b815260206004820152602760248201527f4552524f523a4255432d3037303a4143544956455f494e56414c49445f5452416044820152662729a4aa24a7a760c91b6064820152608401610380565b6107b6565b600182600381111561239157634e487b7160e01b600052602160045260246000fd5b14156124405760008160038111156123b957634e487b7160e01b600052602160045260246000fd5b14806123e4575060028160038111156123e257634e487b7160e01b600052602160045260246000fd5b145b61236a5760405162461bcd60e51b815260206004820152602760248201527f4552524f523a4255432d3037313a4c4f434b45445f494e56414c49445f5452416044820152662729a4aa24a7a760c91b6064820152608401610380565b600282600381111561246257634e487b7160e01b600052602160045260246000fd5b14156124e757600381600381111561248a57634e487b7160e01b600052602160045260246000fd5b1461236a5760405162461bcd60e51b815260206004820152602760248201527f4552524f523a4255432d3037323a434c4f5345445f494e56414c49445f5452416044820152662729a4aa24a7a760c91b6064820152608401610380565b600382600381111561250957634e487b7160e01b600052602160045260246000fd5b14156125635760405162461bcd60e51b815260206004820152602360248201527f4552524f523a4255432d3037333a4255524e45445f49535f46494e414c5f535460448201526241544560e81b6064820152608401610380565b60405162461bcd60e51b815260206004820152602760248201527f4552524f523a424f432d3037343a494e495449414c5f53544154455f4e4f545f6044820152661210539113115160ca1b6064820152608401610380565b600082815260046020526040902060039081018054839260ff199091169060019084908111156125fb57634e487b7160e01b600052602160045260246000fd5b021790555050600090815260046020526040902042600990910155565b6040518061014001604052806000815260200160008152602001600081526020016000600381111561265a57634e487b7160e01b600052602160045260246000fd5b81526020016060815260200160008152602001600081526020016000815260200160008152602001600081525090565b82805461269690612c44565b90600052602060002090601f0160209004810192826126b857600085556126fe565b82601f106126d15782800160ff198235161785556126fe565b828001600101855582156126fe579182015b828111156126fe5782358255916020019190600101906126e3565b5061270a92915061270e565b5090565b5b8082111561270a576000815560010161270f565b600082601f830112612733578081fd5b815167ffffffffffffffff81111561274d5761274d612cb0565b612760601f8201601f1916602001612bb4565b818152846020838601011115612774578283fd5b612785826020830160208701612c14565b949350505050565b80516003811061041757600080fd5b6000602082840312156127ad578081fd5b81356119f881612cc6565b6000602082840312156127c9578081fd5b81516119f881612cc6565b6000806000806000608086880312156127eb578081fd5b85356127f681612cc6565b945060208601359350604086013567ffffffffffffffff80821115612819578283fd5b818801915088601f83011261282c578283fd5b81358181111561283a578384fd5b89602082850101111561284b578384fd5b96999598505060200195606001359392505050565b600060208284031215612871578081fd5b815167ffffffffffffffff80821115612888578283fd5b9083019060c0828603121561289b578283fd5b6128a560c0612bb4565b82516128b081612cc6565b8152602083810151908201526128c86040840161278d565b60408201526060830151828111156128de578485fd5b6128ea87828601612723565b6060830152506080830151608082015260a083015160a082015280935050505092915050565b6000610120808385031215612923578182fd5b61292c81612bb4565b90506129378361278d565b81526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b6000602082840312156129a6578081fd5b5035919050565b6000602082840312156129be578081fd5b5051919050565b600080604083850312156129d7578182fd5b50508035926020909101359150565b6000806000606084860312156129fa578283fd5b505081359360208301359350604090920135919050565b60008151808452612a29816020860160208601612c14565b601f01601f19169290920160200192915050565b60048110612a5b57634e487b7160e01b600052602160045260246000fd5b9052565b6000602082526119f86020830184612a11565b602081016105e78284612a3d565b60208082526022908201527f4552524f523a4255432d3030313a4e4f545f5249534b504f4f4c5f5345525649604082015261434560f01b606082015260800190565b6000602082528251602083015260208301516040830152604083015160608301526060830151612af56080840182612a3d565b5060808301516101408060a0850152612b12610160850183612a11565b915060a085015160c085015260c085015160e085015260e0850151610100818187015280870151915050610120818187015280870151838701525050508091505092915050565b83815260608101612b6d6020830185612a3d565b6127856040830184612a3d565b858152602081018590526001600160a01b038416604082015260a08101612ba46060830185612a3d565b8260808301529695505050505050565b604051601f8201601f1916810167ffffffffffffffff81118282101715612bdd57612bdd612cb0565b604052919050565b60008219821115612bf857612bf8612c9a565b500190565b600082821015612c0f57612c0f612c9a565b500390565b60005b83811015612c2f578181015183820152602001612c17565b83811115612c3e576000848401525b50505050565b600281046001821680612c5857607f821691505b60208210811415612c7957634e487b7160e01b600052602260045260246000fd5b50919050565b6000600019821415612c9357612c93612c9a565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461040257600080fdfea26469706673582212202c90c44b09882a110500aeecf0b77d6a868254581f199a70003d75b9227e578a64736f6c63430008020033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.