Skip to content

Commit

Permalink
Merge pull request #558 from etherisc/feature/validate-nft-type
Browse files Browse the repository at this point in the history
validate nft type (#512)
  • Loading branch information
doerfli authored Jul 26, 2024
2 parents 93a7619 + 13f2d9c commit 9bed517
Show file tree
Hide file tree
Showing 18 changed files with 133 additions and 114 deletions.
2 changes: 2 additions & 0 deletions contracts/distribution/BasicDistribution.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.20;

import {Distribution} from "./Distribution.sol";
import {DISTRIBUTOR} from "../type/ObjectType.sol";
import {IAuthorization} from "../authorization/IAuthorization.sol";
import {NftId} from "../type/NftId.sol";
import {ReferralId} from "../type/Referral.sol";
Expand Down Expand Up @@ -81,6 +82,7 @@ contract BasicDistribution is
external
virtual
onlyOwner()
onlyNftOfType(distributorNftId, DISTRIBUTOR())
restricted()
{
_updateDistributorType(distributorNftId, distributorType, data);
Expand Down
3 changes: 2 additions & 1 deletion contracts/distribution/Distribution.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.20;

import {Amount} from "../type/Amount.sol";
import {COMPONENT, DISTRIBUTION} from "../type/ObjectType.sol";
import {COMPONENT, DISTRIBUTION, DISTRIBUTOR} from "../type/ObjectType.sol";
import {IAuthorization} from "../authorization/IAuthorization.sol";
import {IDistributionService} from "./IDistributionService.sol";
import {NftId, NftIdLib} from "../type/NftId.sol";
Expand Down Expand Up @@ -128,6 +128,7 @@ abstract contract Distribution is
virtual
restricted()
onlyDistributor()
onlyNftOfType(distributorNftId, DISTRIBUTOR())
onlyNftOwner(distributorNftId)
returns (Amount withdrawnAmount)
{
Expand Down
68 changes: 40 additions & 28 deletions contracts/distribution/DistributionService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ contract DistributionService is
)
external
virtual
onlyNftOfType(distributorNftId, DISTRIBUTOR())
returns (ReferralId referralId)
{
(NftId distributionNftId,, IInstance instance) = _getAndVerifyActiveComponent(DISTRIBUTION());
Expand All @@ -174,36 +175,39 @@ contract DistributionService is
revert ErrorIDistributionServiceExpirationInvalid(expiryAt);
}

InstanceReader instanceReader = instance.getInstanceReader();
DistributorType distributorType = instanceReader.getDistributorInfo(distributorNftId).distributorType;
IDistribution.DistributorTypeInfo memory distributorTypeData = instanceReader.getDistributorTypeInfo(distributorType);
{
InstanceReader instanceReader = instance.getInstanceReader();
DistributorType distributorType = instanceReader.getDistributorInfo(distributorNftId).distributorType;
IDistribution.DistributorTypeInfo memory distributorTypeData = instanceReader.getDistributorTypeInfo(distributorType);

if (distributorTypeData.maxReferralCount < maxReferrals) {
revert ErrorIDistributionServiceMaxReferralsExceeded(distributorTypeData.maxReferralCount);
}
if (distributorTypeData.minDiscountPercentage > discountPercentage) {
revert ErrorIDistributionServiceDiscountTooLow(distributorTypeData.minDiscountPercentage.toInt(), discountPercentage.toInt());
}
if (distributorTypeData.maxDiscountPercentage < discountPercentage) {
revert ErrorIDistributionServiceDiscountTooHigh(distributorTypeData.maxDiscountPercentage.toInt(), discountPercentage.toInt());
}
if (expiryAt.toInt() - TimestampLib.blockTimestamp().toInt() > distributorTypeData.maxReferralLifetime) {
revert ErrorIDistributionServiceExpiryTooLong(distributorTypeData.maxReferralLifetime, expiryAt.toInt());
if (distributorTypeData.maxReferralCount < maxReferrals) {
revert ErrorIDistributionServiceMaxReferralsExceeded(distributorTypeData.maxReferralCount);
}
if (distributorTypeData.minDiscountPercentage > discountPercentage) {
revert ErrorIDistributionServiceDiscountTooLow(distributorTypeData.minDiscountPercentage.toInt(), discountPercentage.toInt());
}
if (distributorTypeData.maxDiscountPercentage < discountPercentage) {
revert ErrorIDistributionServiceDiscountTooHigh(distributorTypeData.maxDiscountPercentage.toInt(), discountPercentage.toInt());
}
if (expiryAt.toInt() - TimestampLib.blockTimestamp().toInt() > distributorTypeData.maxReferralLifetime) {
revert ErrorIDistributionServiceExpiryTooLong(distributorTypeData.maxReferralLifetime, expiryAt.toInt());
}
}

referralId = ReferralLib.toReferralId(distributionNftId, code);
IDistribution.ReferralInfo memory info = IDistribution.ReferralInfo(
distributorNftId,
code,
discountPercentage,
maxReferrals,
0, // used referrals
expiryAt,
data
);

instance.getInstanceStore().createReferral(referralId, info);
return referralId;
{
referralId = ReferralLib.toReferralId(distributionNftId, code);
IDistribution.ReferralInfo memory info = IDistribution.ReferralInfo(
distributorNftId,
code,
discountPercentage,
maxReferrals,
0, // used referrals
expiryAt,
data
);

instance.getInstanceStore().createReferral(referralId, info);
}
}

/// @inheritdoc IDistributionService
Expand All @@ -214,6 +218,7 @@ contract DistributionService is
external
virtual
restricted
onlyNftOfType(distributionNftId, DISTRIBUTION())
{
if (referralIsValid(distributionNftId, referralId)) {
IInstance instance = _getInstanceForDistribution(distributionNftId);
Expand All @@ -232,6 +237,7 @@ contract DistributionService is
external
virtual
restricted
onlyNftOfType(distributionNftId, DISTRIBUTION())
{
IInstance instance = _getInstanceForDistribution(distributionNftId);
InstanceReader reader = instance.getInstanceReader();
Expand Down Expand Up @@ -267,6 +273,7 @@ contract DistributionService is
public
virtual
// TODO: restricted() (once #462 is done)
onlyNftOfType(distributorNftId, DISTRIBUTOR())
returns (Amount withdrawnAmount)
{
(NftId distributionNftId,, IInstance instance) = _getAndVerifyActiveComponent(DISTRIBUTION());
Expand Down Expand Up @@ -304,7 +311,12 @@ contract DistributionService is
}
}

function referralIsValid(NftId distributionNftId, ReferralId referralId) public view returns (bool isValid) {
function referralIsValid(NftId distributionNftId, ReferralId referralId)
public
view
onlyNftOfType(distributionNftId, DISTRIBUTION())
returns (bool isValid)
{
if (distributionNftId.eqz() || referralId.eqz()) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/examples/fire/FireProduct.sol
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ contract FireProduct is
public
restricted()
onlyNftOwner(policyNftId)
onlyNftObjectType(policyNftId, POLICY())
onlyNftOfType(policyNftId, POLICY())
returns (ClaimId claimId, PayoutId payoutId)
{
IPolicy.PolicyInfo memory policyInfo = _getInstanceReader().getPolicyInfo(policyNftId);
Expand Down
57 changes: 31 additions & 26 deletions contracts/oracle/OracleService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ contract OracleService is
external
virtual
// restricted() // add authz
onlyNftOfType(oracleNftId, ORACLE())
returns (
RequestId requestId
)
Expand All @@ -66,36 +67,40 @@ contract OracleService is
ORACLE(),
true); // only active

// TODO move to stronger validation, requester and oracle need to belong to same product cluster
// check that requester and oracle share same instance
if (componentInfo.parentNftId != oracleInfo.parentNftId) {
revert ErrorOracleServiceInstanceMismatch(componentInfo.parentNftId, oracleInfo.parentNftId);
}
{
// TODO move to stronger validation, requester and oracle need to belong to same product cluster
// check that requester and oracle share same instance
if (componentInfo.parentNftId != oracleInfo.parentNftId) {
revert ErrorOracleServiceInstanceMismatch(componentInfo.parentNftId, oracleInfo.parentNftId);
}

// check expiriyAt >= now
if (expiryAt < TimestampLib.blockTimestamp()) {
revert ErrorOracleServiceExpiryInThePast(TimestampLib.blockTimestamp(), expiryAt);
}
// check expiriyAt >= now
if (expiryAt < TimestampLib.blockTimestamp()) {
revert ErrorOracleServiceExpiryInThePast(TimestampLib.blockTimestamp(), expiryAt);
}

// check callbackMethodName.length > 0
if (bytes(callbackMethodName).length == 0) {
revert ErrorOracleServiceCallbackMethodNameEmpty();
// check callbackMethodName.length > 0
if (bytes(callbackMethodName).length == 0) {
revert ErrorOracleServiceCallbackMethodNameEmpty();
}
}

// create request info
IOracle.RequestInfo memory request = IOracle.RequestInfo({
requesterNftId: componentNftId,
callbackMethodName: callbackMethodName,
oracleNftId: oracleNftId,
requestData: requestData,
responseData: "",
respondedAt: TimestampLib.zero(),
expiredAt: expiryAt,
isCancelled: false
});

// store request with instance
requestId = instance.getInstanceStore().createRequest(request);
{
// create request info
IOracle.RequestInfo memory request = IOracle.RequestInfo({
requesterNftId: componentNftId,
callbackMethodName: callbackMethodName,
oracleNftId: oracleNftId,
requestData: requestData,
responseData: "",
respondedAt: TimestampLib.zero(),
expiredAt: expiryAt,
isCancelled: false
});

// store request with instance
requestId = instance.getInstanceStore().createRequest(request);
}

// call oracle component
IOracleComponent(oracleInfo.objectAddress).request(
Expand Down
25 changes: 12 additions & 13 deletions contracts/pool/BasicPool.sol
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import {Amount, AmountLib} from "../type/Amount.sol";
import {InstanceLinkedComponent} from "../shared/InstanceLinkedComponent.sol";
import {Fee, FeeLib} from "../type/Fee.sol";
import {Amount} from "../type/Amount.sol";
import {Fee} from "../type/Fee.sol";
import {IAuthorization} from "../authorization/IAuthorization.sol";
import {IBundleService} from "./IBundleService.sol";
import {IPoolComponent} from "./IPoolComponent.sol";
import {IPoolService} from "./IPoolService.sol";
import {IComponents} from "../instance/module/IComponents.sol";
import {IComponentService} from "../shared/IComponentService.sol";
import {NftId, NftIdLib} from "../type/NftId.sol";
import {BUNDLE, COMPONENT, POOL} from "../type/ObjectType.sol";
import {RoleId, PUBLIC_ROLE} from "../type/RoleId.sol";
import {NftId} from "../type/NftId.sol";
import {BUNDLE} from "../type/ObjectType.sol";
import {RoleId} from "../type/RoleId.sol";
import {Seconds} from "../type/Seconds.sol";
import {Timestamp} from "../type/Timestamp.sol";
import {TokenHandler} from "../shared/TokenHandler.sol";
import {UFixed, UFixedLib} from "../type/UFixed.sol";

import {Pool} from "./Pool.sol";

Expand Down Expand Up @@ -56,6 +48,7 @@ abstract contract BasicPool is
virtual
restricted()
onlyBundleOwner(bundleNftId)
onlyNftOfType(bundleNftId, BUNDLE())
{
_stake(bundleNftId, amount);
}
Expand All @@ -69,6 +62,7 @@ abstract contract BasicPool is
virtual
restricted()
onlyBundleOwner(bundleNftId)
onlyNftOfType(bundleNftId, BUNDLE())
{
_unstake(bundleNftId, amount);
}
Expand All @@ -82,6 +76,7 @@ abstract contract BasicPool is
virtual
restricted()
onlyBundleOwner(bundleNftId)
onlyNftOfType(bundleNftId, BUNDLE())
returns(Timestamp newExpiredAt)
{
return _extend(bundleNftId, lifetimeExtension);
Expand All @@ -93,6 +88,7 @@ abstract contract BasicPool is
virtual
restricted()
onlyBundleOwner(bundleNftId)
onlyNftOfType(bundleNftId, BUNDLE())
{
_lockBundle(bundleNftId);
}
Expand All @@ -103,6 +99,7 @@ abstract contract BasicPool is
virtual
restricted()
onlyBundleOwner(bundleNftId)
onlyNftOfType(bundleNftId, BUNDLE())
{
_unlockBundle(bundleNftId);
}
Expand All @@ -113,6 +110,7 @@ abstract contract BasicPool is
virtual
restricted()
onlyBundleOwner(bundleNftId)
onlyNftOfType(bundleNftId, BUNDLE())
{
_closeBundle(bundleNftId);
}
Expand All @@ -126,6 +124,7 @@ abstract contract BasicPool is
virtual
restricted()
onlyBundleOwner(bundleNftId)
onlyNftOfType(bundleNftId, BUNDLE())
{
_setBundleFee(bundleNftId, fee);
}
Expand Down
14 changes: 9 additions & 5 deletions contracts/pool/Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.20;

import {Amount, AmountLib} from "../type/Amount.sol";
import {BUNDLE, COMPONENT, POOL} from "../type/ObjectType.sol";
import {BUNDLE, COMPONENT, POLICY, POOL} from "../type/ObjectType.sol";
import {ClaimId} from "../type/ClaimId.sol";
import {IBundleService} from "./IBundleService.sol";
import {IAuthorization} from "../authorization/IAuthorization.sol";
Expand All @@ -11,13 +11,12 @@ import {IPoolService} from "./IPoolService.sol";
import {IComponents} from "../instance/module/IComponents.sol";
import {IComponentService} from "../shared/IComponentService.sol";
import {InstanceLinkedComponent} from "../shared/InstanceLinkedComponent.sol";
import {Fee, FeeLib} from "../type/Fee.sol";
import {NftId, NftIdLib} from "../type/NftId.sol";
import {Fee} from "../type/Fee.sol";
import {NftId} from "../type/NftId.sol";
import {RoleId, PUBLIC_ROLE} from "../type/RoleId.sol";
import {Seconds} from "../type/Seconds.sol";
import {Timestamp} from "../type/Timestamp.sol";
import {TokenHandler} from "../shared/TokenHandler.sol";
import {UFixed, UFixedLib} from "../type/UFixed.sol";
import {UFixedLib} from "../type/UFixed.sol";

abstract contract Pool is
InstanceLinkedComponent,
Expand Down Expand Up @@ -62,6 +61,7 @@ abstract contract Pool is
public
virtual
restricted()
onlyNftOfType(applicationNftId, POLICY())
{
if(!applicationMatchesBundle(
applicationNftId,
Expand All @@ -87,6 +87,7 @@ abstract contract Pool is
public
virtual
restricted()
onlyNftOfType(policyNftId, POLICY())
{
// default implementation is empty
}
Expand All @@ -105,6 +106,8 @@ abstract contract Pool is
public
virtual
view
onlyNftOfType(applicationNftId, POLICY())
onlyNftOfType(bundleNftId, BUNDLE())
returns (bool isMatching)
{
return true;
Expand All @@ -116,6 +119,7 @@ abstract contract Pool is
virtual
restricted()
onlyBundleOwner(bundleNftId)
onlyNftOfType(bundleNftId, BUNDLE())
returns (Amount withdrawnAmount)
{
return _withdrawBundleFees(bundleNftId, amount);
Expand Down
2 changes: 1 addition & 1 deletion contracts/product/PricingService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ contract PricingService is
{

// if the referral is not valid, then the distribution owner gets everything
if (! _distributionService.referralIsValid(productInfo.distributionNftId, referralId)) {
if (productInfo.distributionNftId.eqz() || ! _distributionService.referralIsValid(productInfo.distributionNftId, referralId)) {
premium.distributionOwnerFeeFixAmount = premium.distributionFeeFixAmount;
premium.distributionOwnerFeeVarAmount = premium.distributionFeeVarAmount;
premium.premiumAmount = premium.fullPremiumAmount;
Expand Down
Loading

0 comments on commit 9bed517

Please sign in to comment.