Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V4.2.0 #206

Merged
merged 12 commits into from
Jun 27, 2024
10 changes: 5 additions & 5 deletions .github/workflows/publish-prerelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ on:

jobs:
build:
if: 'github.event.release.prerelease'
if: "github.event.release.prerelease"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- run: npm ci
- run: npm run build
- name: Run test coverage
Expand All @@ -32,7 +32,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
registry-url: https://registry.npmjs.org/
- run: npm ci
- run: npm run build
Expand All @@ -47,9 +47,9 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
registry-url: https://npm.pkg.github.com/
scope: '@tokenysolutions'
scope: "@tokenysolutions"
- run: npm ci
- run: npm run build
- run: npm publish --tag beta
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ on:

jobs:
build:
if: '!github.event.release.prerelease'
if: "!github.event.release.prerelease"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
- run: npm ci
- run: npm run build
- name: Run test coverage
Expand All @@ -32,7 +32,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
registry-url: https://registry.npmjs.org/
- run: npm ci
- run: npm run build
Expand All @@ -47,9 +47,9 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
node-version: 18
registry-url: https://npm.pkg.github.com/
scope: '@tokenysolutions'
scope: "@tokenysolutions"
- run: npm ci
- run: npm run build
- run: npm publish
Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/push_checking.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
node-version: [18.x]

steps:
- name: Checkout
uses: 'actions/checkout@master'
uses: "actions/checkout@master"

- name: Set Node.js
uses: actions/setup-node@v3
Expand All @@ -20,6 +20,8 @@ jobs:
run: npm ci
- name: Lint Solidity sources
run: npm run lint:sol
- name: Build contracts
run: npm run build
- name: Lint TypeScript sources
run: npm run lint:ts

Expand All @@ -28,11 +30,11 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
node-version: [18.x]

steps:
- name: Checkout
uses: 'actions/checkout@master'
uses: "actions/checkout@master"

- name: Set Node.js
uses: actions/setup-node@v3
Expand Down
3 changes: 0 additions & 3 deletions .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

node ./scripts/commit-msg.js $1 && npx --no-install commitlint --edit $1
4 changes: 0 additions & 4 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +0,0 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged
337 changes: 214 additions & 123 deletions contracts/token/IToken.sol

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions contracts/token/Token.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ import "../roles/AgentRoleUpgradeable.sol";

contract Token is IToken, AgentRoleUpgradeable, TokenStorage {

error AddressNotAgent(address agent);

error AgentNotAuthorized(address agent, string reason);

/// modifiers

/// @dev Modifier to make a function callable only when the contract is not paused.
Expand Down Expand Up @@ -186,6 +190,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage {
* @dev See {IToken-pause}.
*/
function pause() external override onlyAgent whenNotPaused {
if(getAgentRestrictions(msg.sender).disablePause) {
revert AgentNotAuthorized(msg.sender, "pause disabled");
}
_tokenPaused = true;
emit Paused(msg.sender);
}
Expand All @@ -194,6 +201,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage {
* @dev See {IToken-unpause}.
*/
function unpause() external override onlyAgent whenPaused {
if(getAgentRestrictions(msg.sender).disablePause) {
revert AgentNotAuthorized(msg.sender, "pause disabled");
}
_tokenPaused = false;
emit Unpaused(msg.sender);
}
Expand All @@ -207,6 +217,25 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage {
}
}

/**
* @dev See {IToken-setAgentRestrictions}.
*/
function setAgentRestrictions(address agent, TokenRoles memory restrictions) external override onlyOwner {
if(!isAgent(agent)) {
revert AddressNotAgent(agent);
}
_agentsRestrictions[agent] = restrictions;
emit AgentRestrictionsSet(
agent,
restrictions.disableMint,
restrictions.disableBurn,
restrictions.disableAddressFreeze,
restrictions.disableForceTransfer,
restrictions.disablePartialFreeze,
restrictions.disablePause,
restrictions.disableRecovery );
}

/**
* @notice ERC-20 overridden function that include logic to check for trade validity.
* Require that the from and to addresses are not frozen.
Expand Down Expand Up @@ -299,6 +328,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage {
address _newWallet,
address _investorOnchainID
) external override onlyAgent returns (bool) {
if(getAgentRestrictions(msg.sender).disableRecovery) {
revert AgentNotAuthorized(msg.sender, "recovery disabled");
}
require(balanceOf(_lostWallet) != 0, "no tokens to recover");
IIdentity _onchainID = IIdentity(_investorOnchainID);
bytes32 _key = keccak256(abi.encode(_newWallet));
Expand Down Expand Up @@ -433,6 +465,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage {
address _to,
uint256 _amount
) public override onlyAgent returns (bool) {
if(getAgentRestrictions(msg.sender).disableForceTransfer) {
revert AgentNotAuthorized(msg.sender, "forceTransfer disabled");
}
require(balanceOf(_from) >= _amount, "sender balance too low");
uint256 freeBalance = balanceOf(_from) - (_frozenTokens[_from]);
if (_amount > freeBalance) {
Expand All @@ -452,6 +487,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage {
* @dev See {IToken-mint}.
*/
function mint(address _to, uint256 _amount) public override onlyAgent {
if(getAgentRestrictions(msg.sender).disableMint) {
revert AgentNotAuthorized(msg.sender, "mint disabled");
}
require(_tokenIdentityRegistry.isVerified(_to), "Identity is not verified.");
require(_tokenCompliance.canTransfer(address(0), _to, _amount), "Compliance not followed");
_mint(_to, _amount);
Expand All @@ -462,6 +500,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage {
* @dev See {IToken-burn}.
*/
function burn(address _userAddress, uint256 _amount) public override onlyAgent {
if(getAgentRestrictions(msg.sender).disableBurn) {
revert AgentNotAuthorized(msg.sender, "burn disabled");
}
require(balanceOf(_userAddress) >= _amount, "cannot burn more than balance");
uint256 freeBalance = balanceOf(_userAddress) - _frozenTokens[_userAddress];
if (_amount > freeBalance) {
Expand All @@ -477,6 +518,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage {
* @dev See {IToken-setAddressFrozen}.
*/
function setAddressFrozen(address _userAddress, bool _freeze) public override onlyAgent {
if(getAgentRestrictions(msg.sender).disableAddressFreeze) {
revert AgentNotAuthorized(msg.sender, "address freeze disabled");
}
_frozen[_userAddress] = _freeze;

emit AddressFrozen(_userAddress, _freeze, msg.sender);
Expand All @@ -486,6 +530,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage {
* @dev See {IToken-freezePartialTokens}.
*/
function freezePartialTokens(address _userAddress, uint256 _amount) public override onlyAgent {
if(getAgentRestrictions(msg.sender).disablePartialFreeze) {
revert AgentNotAuthorized(msg.sender, "partial freeze disabled");
}
uint256 balance = balanceOf(_userAddress);
require(balance >= _frozenTokens[_userAddress] + _amount, "Amount exceeds available balance");
_frozenTokens[_userAddress] = _frozenTokens[_userAddress] + (_amount);
Expand All @@ -496,6 +543,9 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage {
* @dev See {IToken-unfreezePartialTokens}.
*/
function unfreezePartialTokens(address _userAddress, uint256 _amount) public override onlyAgent {
if(getAgentRestrictions(msg.sender).disablePartialFreeze) {
revert AgentNotAuthorized(msg.sender, "partial freeze disabled");
}
require(_frozenTokens[_userAddress] >= _amount, "Amount should be less than or equal to frozen tokens");
_frozenTokens[_userAddress] = _frozenTokens[_userAddress] - (_amount);
emit TokensUnfrozen(_userAddress, _amount);
Expand Down Expand Up @@ -528,6 +578,13 @@ contract Token is IToken, AgentRoleUpgradeable, TokenStorage {
return _balances[_userAddress];
}

/**
* @dev See {IToken-getAgentRestrictions}.
*/
function getAgentRestrictions(address agent) public view override returns (TokenRoles memory) {
return _agentsRestrictions[agent];
}

/**
* @dev See {ERC20-_transfer}.
*/
Expand Down
5 changes: 4 additions & 1 deletion contracts/token/TokenStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
pragma solidity 0.8.17;
import "../compliance/modular/IModularCompliance.sol";
import "../registry/interface/IIdentityRegistry.sol";
import "./TokenStructs.sol";

contract TokenStorage {
/// @dev ERC20 basic variables
Expand All @@ -90,9 +91,11 @@ contract TokenStorage {
/// @dev Compliance contract linked to the onchain validator system
IModularCompliance internal _tokenCompliance;

mapping(address => TokenRoles) internal _agentsRestrictions;

/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
*/
uint256[49] private __gap;
uint256[48] private __gap;
}
75 changes: 75 additions & 0 deletions contracts/token/TokenStructs.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@

// SPDX-License-Identifier: GPL-3.0
//
// :+#####%%%%%%%%%%%%%%+
// .-*@@@%+.:+%@@@@@%%#***%@@%=
// :=*%@@@#=. :#@@% *@@@%=
// .-+*%@%*-.:+%@@@@@@+. -*+: .=#. :%@@@%-
// :=*@@@@%%@@@@@@@@@%@@@- .=#@@@%@%= =@@@@#.
// -=+#%@@%#*=:. :%@@@@%. -*@@#*@@@@@@@#=:- *@@@@+
// =@@%=:. :=: *@@@@@%#- =%*%@@@@#+-. =+ :%@@@%-
// -@@%. .+@@@ =+=-. @@#- +@@@%- =@@@@%:
// :@@@. .+@@#%: : .=*=-::.-%@@@+*@@= +@@@@#.
// %@@: +@%%* =%@@@@@@@@@@@#. .*@%- +@@@@*.
// #@@= .+@@@@%:=*@@@@@- :%@%: .*@@@@+
// *@@* +@@@#-@@%-:%@@* +@@#. :%@@@@-
// -@@% .:-=++*##%%%@@@@@@@@@@@@*. :@+.@@@%: .#@@+ =@@@@#:
// .@@@*-+*#%%%@@@@@@@@@@@@@@@@%%#**@@%@@@. *@=*@@# :#@%= .#@@@@#-
// -%@@@@@@@@@@@@@@@*+==-:-@@@= *@# .#@*-=*@@@@%= -%@@@* =@@@@@%-
// -+%@@@#. %@%%= -@@:+@: -@@* *@@*-:: -%@@%=. .*@@@@@#
// *@@@* +@* *@@##@@- #@*@@+ -@@= . :+@@@#: .-+@@@%+-
// +@@@%*@@:..=@@@@* .@@@* .#@#. .=+- .=%@@@*. :+#@@@@*=:
// =@@@@%@@@@@@@@@@@@@@@@@@@@@@%- :+#*. :*@@@%=. .=#@@@@%+:
// .%@@= ..... .=#@@+. .#@@@*: -*%@@@@%+.
// +@@#+===---:::... .=%@@*- +@@@+. -*@@@@@%+.
// -@@@@@@@@@@@@@@@@@@@@@@%@@@@= -@@@+ -#@@@@@#=.
// ..:::---===+++***###%%%@@@#- .#@@+ -*@@@@@#=.
// @@@@@@+. +@@*. .+@@@@@%=.
// -@@@@@= =@@%: -#@@@@%+.
// +@@@@@. =@@@= .+@@@@@*:
// #@@@@#:%@@#. :*@@@@#-
// @@@@@%@@@= :#@@@@+.
// :@@@@@@@#.:#@@@%-
// +@@@@@@-.*@@@*:
// #@@@@#.=@@@+.
// @@@@+-%@%=
// :@@@#%@%=
// +@@@@%-
// :#%%=
//

/**
* NOTICE
*
* The T-REX software is licensed under a proprietary license or the GPL v.3.
* If you choose to receive it under the GPL v.3 license, the following applies:
* T-REX is a suite of smart contracts implementing the ERC-3643 standard and
* developed by Tokeny to manage and transfer financial assets on EVM blockchains
*
* Copyright (C) 2023, Tokeny sàrl.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

pragma solidity 0.8.17;

struct TokenRoles {
bool disableMint;
bool disableBurn;
bool disablePartialFreeze;
bool disableAddressFreeze;
bool disableRecovery;
bool disableForceTransfer;
bool disablePause;
}
Loading
Loading