Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion contracts/src/DeployScript.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ contract DeployScript is Script {
assetHubAgentID: assetHubAgentID,
assetHubCreateAssetFee: uint128(vm.envUint("CREATE_ASSET_FEE")),
assetHubReserveTransferFee: uint128(vm.envUint("RESERVE_TRANSFER_FEE")),
exchangeRate: ud60x18(vm.envUint("EXCHANGE_RATE"))
exchangeRate: ud60x18(vm.envUint("EXCHANGE_RATE")),
multiplier: ud60x18(vm.envUint("FEE_MULTIPLIER"))
});

GatewayProxy gateway = new GatewayProxy(address(gatewayLogic), abi.encode(config));
Expand Down
15 changes: 12 additions & 3 deletions contracts/src/Gateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ contract Gateway is IGateway, IInitializable {
SetPricingParametersParams memory params = abi.decode(data, (SetPricingParametersParams));
pricing.exchangeRate = params.exchangeRate;
pricing.deliveryCost = params.deliveryCost;
pricing.multiplier = params.multiplier;
emit PricingParametersChanged();
}

Expand Down Expand Up @@ -462,19 +463,24 @@ contract Gateway is IGateway, IInitializable {
}

// Convert foreign currency to native currency (ROC/KSM/DOT -> ETH)
function _convertToNative(UD60x18 exchangeRate, uint256 amount) internal view returns (uint256) {
function _convertToNative(UD60x18 exchangeRate, UD60x18 multiplier, uint256 amount)
internal
view
returns (uint256)
{
UD60x18 amountFP = convert(amount);
UD60x18 ethDecimals = convert(1e18);
UD60x18 foreignDecimals = convert(10).pow(convert(uint256(FOREIGN_TOKEN_DECIMALS)));
UD60x18 nativeAmountFP = amountFP.mul(exchangeRate).div(foreignDecimals).mul(ethDecimals);
UD60x18 nativeAmountFP = multiplier.mul(amountFP).mul(exchangeRate).div(foreignDecimals).mul(ethDecimals);
uint256 nativeAmount = convert(nativeAmountFP);
return nativeAmount;
}

// Calculate the fee for accepting an outbound message
function _calculateFee(Costs memory costs) internal view returns (uint256) {
PricingStorage.Layout storage pricing = PricingStorage.layout();
return costs.native + _convertToNative(pricing.exchangeRate, pricing.deliveryCost + costs.foreign);
return costs.native
+ _convertToNative(pricing.exchangeRate, pricing.multiplier, pricing.deliveryCost + costs.foreign);
}

// Submit an outbound message to Polkadot, after taking fees
Expand Down Expand Up @@ -569,6 +575,8 @@ contract Gateway is IGateway, IInitializable {
uint128 assetHubReserveTransferFee;
/// @dev extra fee to discourage spamming
uint256 registerTokenFee;
/// @dev Fee multiplier
UD60x18 multiplier;
}

/// @dev Initialize storage in the gateway
Expand Down Expand Up @@ -613,6 +621,7 @@ contract Gateway is IGateway, IInitializable {
PricingStorage.Layout storage pricing = PricingStorage.layout();
pricing.exchangeRate = config.exchangeRate;
pricing.deliveryCost = config.deliveryCost;
pricing.multiplier = config.multiplier;

// Initialize assets storage
AssetsStorage.Layout storage assets = AssetsStorage.layout();
Expand Down
2 changes: 2 additions & 0 deletions contracts/src/Params.sol
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,6 @@ struct SetPricingParametersParams {
UD60x18 exchangeRate;
/// @dev The cost of delivering messages to BridgeHub in DOT
uint128 deliveryCost;
/// @dev Fee multiplier
UD60x18 multiplier;
}
2 changes: 2 additions & 0 deletions contracts/src/storage/PricingStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ library PricingStorage {
UD60x18 exchangeRate;
/// @dev The cost of delivering messages to BridgeHub in DOT
uint128 deliveryCost;
/// @dev Fee multiplier
UD60x18 multiplier;
}

bytes32 internal constant SLOT = keccak256("org.snowbridge.storage.pricing");
Expand Down
22 changes: 15 additions & 7 deletions contracts/test/Gateway.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ contract GatewayTest is Test {

// ETH/DOT exchange rate
UD60x18 public exchangeRate = ud60x18(0.0025e18);
UD60x18 public multiplier = ud60x18(1e18);

function setUp() public {
AgentExecutor executor = new AgentExecutor();
Expand All @@ -103,7 +104,8 @@ contract GatewayTest is Test {
assetHubAgentID: assetHubAgentID,
assetHubCreateAssetFee: createTokenFee,
assetHubReserveTransferFee: sendTokenFee,
exchangeRate: exchangeRate
exchangeRate: exchangeRate,
multiplier: multiplier
});
gateway = new GatewayProxy(address(gatewayLogic), abi.encode(config));
GatewayMock(address(gateway)).setCommitmentsAreVerified(true);
Expand Down Expand Up @@ -497,7 +499,8 @@ contract GatewayTest is Test {
assetHubAgentID: assetHubAgentID,
assetHubCreateAssetFee: createTokenFee,
assetHubReserveTransferFee: sendTokenFee,
exchangeRate: exchangeRate
exchangeRate: exchangeRate,
multiplier: multiplier
});

UpgradeParams memory params = UpgradeParams({
Expand All @@ -516,7 +519,7 @@ contract GatewayTest is Test {

testSetPricingParameters();
uint256 fee = IGateway(address(gateway)).quoteRegisterTokenFee();
assertEq(fee, 10000000000000000);
assertEq(fee, 20000000000000001);

testCreateAgent();
assertNotEq(GatewayMock(address(gateway)).agentOf(agentID), address(0));
Expand All @@ -538,7 +541,7 @@ contract GatewayTest is Test {

// Verify that storage was not overwritten
fee = IGateway(address(gateway)).quoteRegisterTokenFee();
assertEq(fee, 10000000000000000);
assertEq(fee, 20000000000000001);
assertNotEq(GatewayMock(address(gateway)).agentOf(agentID), address(0));
}

Expand Down Expand Up @@ -875,14 +878,19 @@ contract GatewayTest is Test {
function testSetPricingParameters() public {
uint256 fee = IGateway(address(gateway)).quoteRegisterTokenFee();
assertEq(fee, 5000000000000000);
// Double the exchangeRate
// Double the exchangeRate and multiplier.
GatewayMock(address(gateway)).setPricingParametersPublic(
abi.encode(
SetPricingParametersParams({exchangeRate: exchangeRate.mul(convert(2)), deliveryCost: outboundFee})
SetPricingParametersParams({
exchangeRate: exchangeRate.mul(convert(2)),
multiplier: multiplier.mul(convert(2)),
deliveryCost: outboundFee
})
)
);
// Should expect 4x fee increase
fee = IGateway(address(gateway)).quoteRegisterTokenFee();
assertEq(fee, 10000000000000000);
assertEq(fee, 20000000000000001);
}

function testSendTokenToForeignDestWithInvalidFee() public {
Expand Down