Skip to content

Commit 5e2f2af

Browse files
security token added
1 parent be71df5 commit 5e2f2af

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.20;
3+
4+
import {Script} from "forge-std/Script.sol";
5+
import {SecurityToken} from "../../src/tokens/SecurityToken.sol";
6+
7+
contract DeploySecurityToken is Script {
8+
function run() external {
9+
// Retrieve private key from environment
10+
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
11+
12+
// Start broadcasting transactions
13+
vm.startBroadcast(deployerPrivateKey);
14+
15+
// Deploy the token
16+
SecurityToken token = new SecurityToken(
17+
"Security Token",
18+
"STKN",
19+
vm.addr(deployerPrivateKey)
20+
);
21+
22+
vm.stopBroadcast();
23+
}
24+
}

src/tokens/SecurityToken.sol

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.20;
3+
4+
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
6+
7+
contract SecurityToken is ERC20, Ownable {
8+
// Identity Registry to store KYC/AML status
9+
mapping(address => bool) public identityRegistry;
10+
11+
// Transfer restriction status
12+
bool public transfersFrozen;
13+
14+
// Events
15+
event AddedToIdentityRegistry(address indexed investor);
16+
event RemovedFromIdentityRegistry(address indexed investor);
17+
event TransfersFrozen();
18+
event TransfersUnfrozen();
19+
20+
constructor(
21+
string memory name,
22+
string memory symbol,
23+
address initialOwner
24+
) ERC20(name, symbol) Ownable(initialOwner) {}
25+
26+
// Modifier to check if an address is verified
27+
modifier onlyVerified(address _address) {
28+
require(identityRegistry[_address], "Identity not verified");
29+
_;
30+
}
31+
32+
// Add an investor to the identity registry
33+
function addToIdentityRegistry(address investor) external onlyOwner {
34+
identityRegistry[investor] = true;
35+
emit AddedToIdentityRegistry(investor);
36+
}
37+
38+
// Remove an investor from the identity registry
39+
function removeFromIdentityRegistry(address investor) external onlyOwner {
40+
identityRegistry[investor] = false;
41+
emit RemovedFromIdentityRegistry(investor);
42+
}
43+
44+
// Freeze all transfers
45+
function freezeTransfers() external onlyOwner {
46+
transfersFrozen = true;
47+
emit TransfersFrozen();
48+
}
49+
50+
// Unfreeze all transfers
51+
function unfreezeTransfers() external onlyOwner {
52+
transfersFrozen = false;
53+
emit TransfersUnfrozen();
54+
}
55+
56+
// Mint new tokens (only owner)
57+
function mint(
58+
address to,
59+
uint256 amount
60+
) external onlyOwner onlyVerified(to) {
61+
_mint(to, amount);
62+
}
63+
64+
// Override transfer function to add compliance checks
65+
function transfer(
66+
address to,
67+
uint256 amount
68+
) public override onlyVerified(msg.sender) onlyVerified(to) returns (bool) {
69+
require(!transfersFrozen, "Transfers are frozen");
70+
return super.transfer(to, amount);
71+
}
72+
73+
// Override transferFrom function to add compliance checks
74+
function transferFrom(
75+
address from,
76+
address to,
77+
uint256 amount
78+
) public override onlyVerified(from) onlyVerified(to) returns (bool) {
79+
require(!transfersFrozen, "Transfers are frozen");
80+
return super.transferFrom(from, to, amount);
81+
}
82+
}

test/token/SecurityToken.t.sol

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.20;
3+
4+
import {Test} from "forge-std/Test.sol";
5+
import {SecurityToken} from "../../src/tokens/SecurityToken.sol";
6+
7+
contract SecurityTokenTest is Test {
8+
SecurityToken public token;
9+
address public owner;
10+
address public alice;
11+
address public bob;
12+
13+
function setUp() public {
14+
owner = address(this);
15+
alice = address(0x1);
16+
bob = address(0x2);
17+
18+
// Deploy token
19+
token = new SecurityToken("Security Token", "STKN", owner);
20+
21+
// Add alice and bob to identity registry
22+
token.addToIdentityRegistry(alice);
23+
token.addToIdentityRegistry(bob);
24+
25+
// Mint initial tokens to alice
26+
token.mint(alice, 1000);
27+
}
28+
29+
function testInitialSetup() public {
30+
assertEq(token.name(), "Security Token");
31+
assertEq(token.symbol(), "STKN");
32+
assertEq(token.balanceOf(alice), 1000);
33+
}
34+
35+
function testTransferBetweenVerifiedAddresses() public {
36+
vm.prank(alice);
37+
token.transfer(bob, 500);
38+
assertEq(token.balanceOf(alice), 500);
39+
assertEq(token.balanceOf(bob), 500);
40+
}
41+
42+
function testFailTransferToUnverifiedAddress() public {
43+
address unverified = address(0x3);
44+
vm.prank(alice);
45+
token.transfer(unverified, 500);
46+
}
47+
48+
function testFailTransferWhenFrozen() public {
49+
token.freezeTransfers();
50+
vm.prank(alice);
51+
token.transfer(bob, 500);
52+
}
53+
54+
function testIdentityRegistryManagement() public {
55+
address charlie = address(0x4);
56+
assertFalse(token.identityRegistry(charlie));
57+
58+
token.addToIdentityRegistry(charlie);
59+
assertTrue(token.identityRegistry(charlie));
60+
61+
token.removeFromIdentityRegistry(charlie);
62+
assertFalse(token.identityRegistry(charlie));
63+
}
64+
}

0 commit comments

Comments
 (0)