Skip to content

Commit

Permalink
feat: add social network adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
nmlinaric committed Mar 6, 2024
1 parent 1fe57a3 commit e5be915
Show file tree
Hide file tree
Showing 7 changed files with 400 additions and 0 deletions.
20 changes: 20 additions & 0 deletions contracts/TestContracts.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ pragma solidity 0.8.11;
import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol";
import "./handlers/ERCHandlerHelpers.sol";
import "./interfaces/IERC20Plus.sol";
import "./interfaces/ISocialNetworkController.sol";


contract NoArgument {
event NoArgumentCalled();
Expand Down Expand Up @@ -237,3 +239,21 @@ contract TestDeposit {
emit TestExecute(depositor, num, addresses[1], message);
}
}

contract SocialNetworkControllerMock {
uint256 public constant HEART_BTC = 369;
uint256 public bitcoinStaked = 0;
address public _socialNetworkBitcoin;

event Stake(address indexed user, uint256 amount);

function setSocialNetworkBitcoinAddress(address socialNetworkBitcoin) public {
_socialNetworkBitcoin = _socialNetworkBitcoin;
}

function stakeBTC(uint256 amount, address recipient) external {
uint256 mintAmount = amount * HEART_BTC;
bitcoinStaked += amount;
emit Stake(recipient, mintAmount);
}
}
53 changes: 53 additions & 0 deletions contracts/adapters/SocialNetworkAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 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/ISocialNetworkController.sol";
import "../interfaces/ISocialNetworkBitcoin.sol";
import "../interfaces/ISocialNetworkPercentageFeeHandler.sol";
import "../handlers/fee/SocialNetworkPercentageFeeHandler.sol";


contract SocialNetworkAdapter {

address public immutable _permissionlessHandler;
ISocialNetworkController public immutable _socialNetworkController;
ISocialNetworkPercentageFeeHandler public immutable _feeHandler;

mapping(string => mapping(address => uint256)) public _btcToEthDepositorToStakedAmount;


function _onlyPermissionlessHandler() private view {
require(msg.sender == _permissionlessHandler, "sender must be bridge contract");
}

modifier onlyPermissionlessHandler() {
_onlyPermissionlessHandler();
_;
}

constructor (
address permissionlessHandler,
ISocialNetworkPercentageFeeHandler feeHandler,
ISocialNetworkController socialNetworkController
) {
_permissionlessHandler = permissionlessHandler;
_socialNetworkController = socialNetworkController;
_feeHandler = feeHandler;
}

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));

(uint256 fee) = _feeHandler.calculateFee(amount);
uint256 stakedAmount = amount - fee;

_btcToEthDepositorToStakedAmount[btcDepositorAddress][ethDepositorAddress] = stakedAmount;
// _socialNetworkController._socialNetworkBitcoin(); //.mint(address(_feeHandler), fee);
_socialNetworkController.stakeBTC(amount, ethDepositorAddress);
}
}
129 changes: 129 additions & 0 deletions contracts/handlers/fee/SocialNetworkPercentageFeeHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// The Licensed Work is (c) 2022 Sygma
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.11;

import "../../utils/AccessControl.sol";
import {ERC20Safe} from "../../ERC20Safe.sol";

/**
@title Handles deposit fees.
@author ChainSafe Systems.
@notice This contract is intended to be used with the Bridge contract.
*/
contract SocialNetworkPercentageFeeHandler is ERC20Safe, AccessControl {
uint32 public constant HUNDRED_PERCENT = 1e8;
uint256 public _fee;
address public _socialNetworkBitcoin;

struct Bounds {
uint128 lowerBound; // min fee in token amount
uint128 upperBound; // max fee in token amount
}

Bounds public _feeBounds;

event FeeChanged(uint256 newFee);
event FeeBoundsChanged(uint256 newLowerBound, uint256 newUpperBound);
/**
@notice This event is emitted when the fee is distributed to an address.
@param recipient Address that receives the distributed fee.
@param amount Amount that is distributed.
*/
event FeeDistributed(
address recipient,
uint256 amount
);

modifier onlyAdmin() {
require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "sender doesn't have admin role");
_;
}


constructor () {
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
}


/**
@notice Calculates fee for deposit.
@param depositAmount Additional data to be passed to the fee handler.
@return fee Returns the fee amount.
*/
function calculateFee(uint256 depositAmount) external view returns(uint256 fee) {
return _calculateFee(depositAmount);
}

function _calculateFee(uint256 depositAmount) internal view returns(uint256 fee) {
Bounds memory bounds = _feeBounds;

fee = depositAmount * _fee / HUNDRED_PERCENT; // 10000 for BPS and 10000 to avoid precision loss

if (fee < bounds.lowerBound) {
fee = bounds.lowerBound;
}

// if upper bound is not set, fee is % of token amount
else if (fee > bounds.upperBound && bounds.upperBound > 0) {
fee = bounds.upperBound;
}

return fee;
}

// Admin functions


/**
@notice Sets Social Network Bitcoin address..
@notice Only callable by admin.
@param socialNetworkBitcoin Value {_socialNetworkBitcoin} that will be set.
*/
function setSocialNetworkBitcoinAddress(address socialNetworkBitcoin) external onlyAdmin {
_socialNetworkBitcoin = _socialNetworkBitcoin;
}

/**
@notice Sets new value for lower and upper fee bounds, both are in token amount.
@notice Only callable by admin.
@param newLowerBound Value {_newLowerBound} will be updated to.
@param newUpperBound Value {_newUpperBound} will be updated to.
*/
function changeFeeBounds(uint128 newLowerBound, uint128 newUpperBound) external onlyAdmin {
require(newUpperBound == 0 || (newUpperBound > newLowerBound), "Upper bound must be larger than lower bound or 0");
Bounds memory existingBounds = _feeBounds;
require(existingBounds.lowerBound != newLowerBound ||
existingBounds.upperBound != newUpperBound,
"Current bounds are equal to new bounds"
);

Bounds memory newBounds = Bounds(newLowerBound, newUpperBound);
_feeBounds = newBounds;

emit FeeBoundsChanged(newLowerBound, newUpperBound);
}

/**
@notice Only callable by admin.
@param newFee Value to which fee will be updated to for the provided {destinantionDomainID} and {resourceID}.
*/
function changeFee(uint256 newFee) external onlyAdmin {
require(_fee != newFee, "Current fee is equal to new fee");
_fee = newFee;
emit FeeChanged(newFee);
}

/**
@notice Transfers tokens from the contract to the specified addresses. The parameters addrs and amounts are mapped 1-1.
This means that the address at index 0 for addrs will receive the amount of tokens from amounts at index 0.
@param addrs Array of addresses to transfer {amounts} to.
@param amounts Array of amounts to transfer to {addrs}.
*/
function transferERC20Fee(address[] calldata addrs, uint[] calldata amounts) external onlyAdmin {
require(addrs.length == amounts.length, "addrs[], amounts[]: diff length");
for (uint256 i = 0; i < addrs.length; i++) {
releaseERC20(_socialNetworkBitcoin, addrs[i], amounts[i]);
emit FeeDistributed(addrs[i], amounts[i]);
}
}
}
11 changes: 11 additions & 0 deletions contracts/interfaces/ISocialNetworkBitcoin.sol
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 ISocialNetworkBitcoin {
function mint(address to, uint256 amount) external;
}
12 changes: 12 additions & 0 deletions contracts/interfaces/ISocialNetworkController.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// 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 ISocialNetworkController {
function _socialNetworkBitcoin() external returns (address);
function stakeBTC (uint256 amount, address ethDepositorAddress) external;
}
12 changes: 12 additions & 0 deletions contracts/interfaces/ISocialNetworkPercentageFeeHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// 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 ISocialNetworkPercentageFeeHandler {
function calculateFee (uint256 depositAmount) external returns(uint256 fee);
}
Loading

0 comments on commit e5be915

Please sign in to comment.