-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
236 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// The Licensed Work is (c) 2022 Sygma | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
pragma solidity 0.8.11; | ||
|
||
import "../interfaces/IBridge.sol"; | ||
import "../interfaces/IERCHandler.sol"; | ||
import "../interfaces/ISocialNetwork.sol"; | ||
import "../handlers/fee/PercentageERC20FeeHandlerEVM.sol"; | ||
import "../ERC20Safe.sol"; | ||
|
||
|
||
contract SocialNetworkAdapter is PercentageERC20FeeHandlerEVM { | ||
|
||
address public immutable _permissionlessHandler; | ||
ISocialNetwork public immutable _socialNetworkController; | ||
|
||
mapping(string => mapping(address => uint256)) public _btcToEthDepositorToAmount; | ||
|
||
|
||
function _onlyPermissionlessHandler() private view { | ||
require(msg.sender == _permissionlessHandler, "sender must be bridge contract"); | ||
} | ||
|
||
modifier onlyPermissionlessHandler() { | ||
_onlyPermissionlessHandler(); | ||
_; | ||
} | ||
|
||
constructor ( | ||
address bridgeAddress, | ||
address permissionlessHandler, | ||
ISocialNetwork socialNetworkController, | ||
address feeHandlerRouterAddress | ||
) PercentageERC20FeeHandlerEVM(bridgeAddress, feeHandlerRouterAddress) { | ||
_permissionlessHandler = permissionlessHandler; | ||
_socialNetworkController = socialNetworkController; | ||
} | ||
|
||
event TestExecute(address depositor, uint256 depositAmount, string btcDepositorAddress); | ||
|
||
function stakeBTC (address ethDepositorAddress, bytes calldata data) external onlyPermissionlessHandler { | ||
(uint256 amount, string memory btcDepositorAddress) = abi.decode(data, (uint256, string)); | ||
|
||
calculateFee( | ||
sender, | ||
fromDomainID, | ||
destinationDomainID, | ||
resourceID, | ||
depositData, | ||
feeData | ||
); | ||
|
||
_btcToEthDepositorToAmount[btcDepositorAddress][ethDepositorAddress] = amount; | ||
_socialNetworkController.stakeBTC(amount, ethDepositorAddress); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// The Licensed Work is (c) 2022 Sygma | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
pragma solidity 0.8.11; | ||
|
||
/** | ||
@title Interface for SocialNetwork adapter. | ||
@author ChainSafe Systems. | ||
*/ | ||
interface ISocialNetwork { | ||
function stakeBTC (uint256 amount, address ethDepositorAddress) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
// The Licensed Work is (c) 2022 Sygma | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
|
||
const TruffleAssert = require("truffle-assertions"); | ||
const Ethers = require("ethers"); | ||
const Helpers = require("../../helpers"); | ||
|
||
const PermissionlessGenericHandlerContract = artifacts.require( | ||
"PermissionlessGenericHandler" | ||
); | ||
const SocialAdapterContract = artifacts.require("SocialNetworkAdapter"); | ||
const SocialNetworkControllerMockContract = artifacts.require("SocialNetworkControllerMock"); | ||
|
||
contract( | ||
"PermissionlessGenericHandler - Social network - [Execute Proposal]", | ||
async (accounts) => { | ||
const originDomainID = 1; | ||
const destinationDomainID = 2; | ||
const expectedDepositNonce = 1; | ||
|
||
const ethDepositorAddress = accounts[1]; | ||
const relayer1Address = accounts[2]; | ||
|
||
const destinationMaxFee = 900000; | ||
|
||
|
||
let BridgeInstance; | ||
let SocialNetworkAdapterInstance; | ||
let SocialNetworkControllerMockInstance; | ||
|
||
let resourceID; | ||
let depositFunctionSignature; | ||
let PermissionlessGenericHandlerInstance; | ||
|
||
beforeEach(async () => { | ||
await Promise.all([ | ||
(BridgeInstance = await Helpers.deployBridge( | ||
destinationDomainID, | ||
accounts[0] | ||
)), | ||
]); | ||
|
||
resourceID = "0x0000000000000000000000000000000000000000000000000000000000000000" | ||
|
||
PermissionlessGenericHandlerInstance = | ||
await PermissionlessGenericHandlerContract.new(BridgeInstance.address); | ||
|
||
SocialNetworkControllerMockInstance = await SocialNetworkControllerMockContract.new(); | ||
SocialNetworkAdapterInstance = await SocialAdapterContract.new( | ||
BridgeInstance.address, | ||
PermissionlessGenericHandlerInstance.address, | ||
SocialNetworkControllerMockInstance.address, | ||
Ethers.constants.AddressZero | ||
) | ||
|
||
depositFunctionSignature = Helpers.getFunctionSignature( | ||
SocialNetworkAdapterInstance, | ||
"stakeBTC" | ||
); | ||
|
||
const PermissionlessGenericHandlerSetResourceData = | ||
Helpers.constructGenericHandlerSetResourceData( | ||
depositFunctionSignature, | ||
Helpers.blankFunctionDepositorOffset, | ||
Helpers.blankFunctionSig | ||
); | ||
await BridgeInstance.adminSetResource( | ||
PermissionlessGenericHandlerInstance.address, | ||
resourceID, | ||
SocialNetworkAdapterInstance.address, | ||
PermissionlessGenericHandlerSetResourceData | ||
); | ||
|
||
// set MPC address to unpause the Bridge | ||
await BridgeInstance.endKeygen(Helpers.mpcAddress); | ||
}); | ||
|
||
it("call with packed depositData should be successful", async () => { | ||
const depositAmount = 5; | ||
const btcDepositorAddress = "btcDepositorAddress" | ||
const executionData = Helpers.abiEncode(["uint", "string"], [depositAmount, btcDepositorAddress]); | ||
|
||
console.log("2324", SocialNetworkAdapterInstance) | ||
|
||
// this mocks prepareDepositData helper function from origin adapter | ||
// this logic is now on implemented on relayers | ||
const preparedExecutionData = | ||
"0x" + | ||
Helpers.abiEncode( | ||
["address", "bytes"], [Ethers.constants.AddressZero, executionData] | ||
).slice(66); | ||
|
||
console.log("preparedExecutionData", preparedExecutionData); | ||
const depositFunctionSignature = Helpers.getFunctionSignature( | ||
SocialNetworkAdapterInstance, | ||
"stakeBTC" | ||
); | ||
const depositData = Helpers.createPermissionlessGenericDepositData( | ||
depositFunctionSignature, | ||
SocialNetworkAdapterInstance.address, | ||
destinationMaxFee, | ||
ethDepositorAddress, | ||
preparedExecutionData | ||
); | ||
|
||
const proposal = { | ||
originDomainID: originDomainID, | ||
depositNonce: expectedDepositNonce, | ||
data: depositData, | ||
resourceID: resourceID, | ||
}; | ||
const proposalSignedData = await Helpers.signTypedProposal( | ||
BridgeInstance.address, | ||
[proposal] | ||
); | ||
|
||
// relayer1 executes the proposal | ||
const executeTx = await BridgeInstance.executeProposal(proposal, proposalSignedData, { | ||
from: relayer1Address, | ||
}); | ||
|
||
const internalTx = await TruffleAssert.createTransactionResult( | ||
SocialNetworkControllerMockInstance, | ||
executeTx.tx | ||
); | ||
|
||
// check that ProposalExecution event is emitted | ||
TruffleAssert.eventEmitted(executeTx, "ProposalExecution", (event) => { | ||
return ( | ||
event.originDomainID.toNumber() === originDomainID && | ||
event.depositNonce.toNumber() === expectedDepositNonce | ||
); | ||
}); | ||
|
||
// check that TestExecute event is emitted | ||
TruffleAssert.eventEmitted(internalTx, "Stake", (event) => { | ||
return ( | ||
event.user === ethDepositorAddress && | ||
// this is for Social network internal logic | ||
// 36900 Social Network Bitcoin (HEART) for every Bitcoin (SAT) deposited | ||
event.amount.toNumber() === depositAmount * 369 | ||
); | ||
}); | ||
|
||
// check that amount is mapped to belonging address | ||
assert.equal( | ||
await SocialNetworkAdapterInstance._btcToEthDepositorToAmount.call( | ||
btcDepositorAddress, | ||
ethDepositorAddress | ||
), | ||
depositAmount | ||
) | ||
}); | ||
} | ||
); |