Skip to content

Commit

Permalink
feat: add centralized connections in solidity and java (#196)
Browse files Browse the repository at this point in the history
* feat: solidity xcall connection added

* feat: icon xcall connection added

* fix: checkfee added

* feat: relayer address in centralized connection

* feat: added build scripts

* feat: solidity tests for centralized connection added

* feat: centralized connection name changed for icon

* fix: review comments addressed for solidity part

* fix: variable admin used for relayer/admin

* fix: review comments addressed for javascore part

* fix: variables in build.gradle in centralized cnnection

* fix: java score constructor

* fix: removed void from constructor

* fix: type of receipts to boolean

* fix: solitity tests resolved

* fix: logic corrected for duplicate message

* fix: fee check added in connection

* fix: centralized connection test added in solidity

* fix: admin check removed from getReceipts

Co-authored-by: redlarva <[email protected]>

* fix: onlyAdmin function

* fix: architecture updated (#214)

* fix: architecture updated

* fix: use connectio sn

* style: formatting code

* added scripts for centralized connections

* feat: centralized-connection javascore tests added

* feat: clam fees tests added

---------

Co-authored-by: red__larva <[email protected]>
Co-authored-by: redlarva <[email protected]>
  • Loading branch information
3 people committed Dec 29, 2023
1 parent d0d8f54 commit 99f68b6
Show file tree
Hide file tree
Showing 12 changed files with 1,019 additions and 8 deletions.
16 changes: 16 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ optimize-cosmwasm:
@echo "Generating optimized cosmwasm for Archway contracts"
sh ./scripts/optimize-cosmwasm.sh

build-solidity:
@echo "Build solidity contracts"
sh ./scripts/optimize-solc.sh build

build-solidity-docker:
@echo "Build solidity contracts"
docker-compose -f ./scripts/docker-compose.yml up solidity

build-java-docker:
@echo "Build java contracts"
docker-compose -f ./scripts/docker-compose.yml up java

build-wasm-docker:
@echo "Build java contracts"
docker-compose -f ./scripts/docker-compose.yml up wasm

gobuild:
go build .

Expand Down
149 changes: 149 additions & 0 deletions contracts/evm/contracts/adapters/CentralizedConnection.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.8.0;
pragma abicoder v2;

import "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol";
import "@xcall/utils/Types.sol";
import "@xcall/contracts/xcall/interfaces/IConnection.sol";
import "@iconfoundation/btp2-solidity-library/interfaces/ICallService.sol";

contract CentralizedConnection is Initializable, IConnection {
mapping(string => uint256) private messageFees;
mapping(string => uint256) private responseFees;
mapping(string => mapping(uint256 => bool)) receipts;
address private xCall;
address private adminAddress;
uint256 public connSn;

event Message(string targetNetwork, uint256 sn, bytes _msg);

modifier onlyAdmin() {
require(msg.sender == this.admin(), "OnlyRelayer");
_;
}

function initialize(address _relayer, address _xCall) public initializer {
xCall = _xCall;
adminAddress = _relayer;
}

/**
@notice Sets the fee to the target network
@param networkId String Network Id of target chain
@param messageFee Integer ( The fee needed to send a Message )
@param responseFee Integer (The fee of the response )
*/
function setFee(
string calldata networkId,
uint256 messageFee,
uint256 responseFee
) external onlyAdmin {
messageFees[networkId] = messageFee;
responseFees[networkId] = responseFee;
}

/**
@notice Gets the fee to the target network
@param to String Network Id of target chain
@param response Boolean ( Whether the responding fee is included )
@return fee Integer (The fee of sending a message to a given destination network )
*/
function getFee(
string memory to,
bool response
) external view override returns (uint256 fee) {
uint256 messageFee = messageFees[to];
if (response == true) {
uint256 responseFee = responseFees[to];
return messageFee + responseFee;
}
return messageFee;
}

/**
@notice Sends the message to a specific network.
@param sn : positive for two-way message, zero for one-way message, negative for response
@param to String ( Network Id of destination network )
@param svc String ( name of the service )
@param sn Integer ( serial number of the xcall message )
@param _msg Bytes ( serialized bytes of Service Message )
*/
function sendMessage(
string calldata to,
string calldata svc,
int256 sn,
bytes calldata _msg
) external payable override {
require(msg.sender == xCall, "Only Xcall can call sendMessage");
uint256 fee;
if (sn > 0) {
fee = this.getFee(to, true);
} else if (sn == 0) {
fee = this.getFee(to, false);
}
require(msg.value >= fee, "Fee is not Sufficient");
connSn++;
emit Message(to, connSn, _msg);
}

/**
@notice Sends the message to a xCall.
@param srcNetwork String ( Network Id )
@param _connSn Integer ( connection message sn )
@param _msg Bytes ( serialized bytes of Service Message )
*/
function recvMessage(
string memory srcNetwork,
uint256 _connSn,
bytes calldata _msg
) public onlyAdmin {
require(!receipts[srcNetwork][_connSn], "Duplicate Message");
receipts[srcNetwork][_connSn] = true;
ICallService(xCall).handleMessage(srcNetwork, _msg);
}

/**
@notice Sends the balance of the contract to the owner(relayer)
*/
function claimFees() public onlyAdmin {
payable(adminAddress).transfer(address(this).balance);
}

/**
@notice Revert a messages, used in special cases where message can't just be dropped
@param sn Integer ( serial number of the xcall message )
*/
function revertMessage(uint256 sn) public onlyAdmin {
ICallService(xCall).handleError(sn);
}

/**
@notice Gets a message receipt
@param srcNetwork String ( Network Id )
@param _connSn Integer ( connection message sn )
@return boolean if is has been recived or not
*/
function getReceipt(
string memory srcNetwork,
uint256 _connSn
) public view returns (bool) {
return receipts[srcNetwork][_connSn];
}

/**
@notice Set the address of the admin.
@param _address The address of the admin.
*/
function setAdmin(address _address) external onlyAdmin {
adminAddress = _address;
}

/**
@notice Gets the address of admin
@return (Address) the address of admin
*/
function admin() external view returns (address) {
return adminAddress;
}
}
13 changes: 7 additions & 6 deletions contracts/evm/script/CallService.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import "@xcall/contracts/xcall/CallService.sol";
import "@xcall/contracts/mocks/multi-protocol-dapp/MultiProtocolSampleDapp.sol";
import "@xcall/contracts/adapters/WormholeAdapter.sol";
import "@xcall/contracts/adapters/LayerZeroAdapter.sol";
import "@xcall/contracts/adapters/CentralizedConnection.sol";

contract DeployCallService is Script {
CallService private proxyXcall;
Expand Down Expand Up @@ -96,16 +97,16 @@ contract DeployCallService is Script {
);
} else if (contractA.compareTo("centralized")) {
address xcall = vm.envAddress(chain.concat("_XCALL"));
address wormholeRelayer = vm.envAddress(
chain.concat("_WORMHOLE_RELAYER")
address centralizedRelayer = vm.envAddress(
chain.concat("_CENTRALIZED_RELAYER")
);

address proxy = Upgrades.deployTransparentProxy(
"WormholeAdapter.sol",
"CentralizedConnection.sol",
msg.sender,
abi.encodeCall(
WormholeAdapter.initialize,
(wormholeRelayer, xcall)
CentralizedConnection.initialize,
(centralizedRelayer, xcall)
)
);
} else if(contractA.compareTo("mock")) {
Expand Down Expand Up @@ -143,7 +144,7 @@ contract DeployCallService is Script {
Upgrades.upgradeProxy(proxy, contractName, "");
} else if (contractA.compareTo("centralized")) {
address proxy = vm.envAddress(
capitalizeString(chain).concat("_XCALL")
capitalizeString(chain).concat("_CENTRALIZED_ADAPTER")
);
Upgrades.upgradeProxy(proxy, contractName, "");
}
Expand Down
Loading

0 comments on commit 99f68b6

Please sign in to comment.