Skip to content

Commit

Permalink
Allow specifying implementation on deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
ben-kaufman committed Jan 10, 2024
1 parent 9cf2794 commit c6e2993
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 86 deletions.
18 changes: 4 additions & 14 deletions contracts/tge/HATAirdropFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ import "./HATAirdrop.sol";
contract HATAirdropFactory is Ownable {
using SafeERC20Upgradeable for IERC20Upgradeable;

address public implementation;

event ImplementationUpdated(address indexed _newImplementation);
event TokensWithdrawn(address indexed _owner, uint256 _amount);
event HATAirdropCreated(
address indexed _hatAirdrop,
Expand All @@ -27,22 +24,14 @@ contract HATAirdropFactory is Ownable {
ITokenLockFactory _tokenLockFactory
);

constructor (address _implementation) {
implementation = _implementation;
}

function updateImplementation(address _newImplementation) external onlyOwner {
implementation = _newImplementation;
emit ImplementationUpdated(_newImplementation);
}

function withdrawTokens(IERC20Upgradeable _token, uint256 _amount) external onlyOwner {
address owner = owner();
_token.safeTransfer(owner, _amount);
emit TokensWithdrawn(owner, _amount);
}

function createHATAirdrop(
address _implementation,
string memory _merkleTreeIPFSRef,
bytes32 _root,
uint256 _startTime,
Expand All @@ -53,7 +42,7 @@ contract HATAirdropFactory is Ownable {
IERC20Upgradeable _token,
ITokenLockFactory _tokenLockFactory
) external onlyOwner returns (address result) {
result = Clones.cloneDeterministic(implementation, keccak256(abi.encodePacked(
result = Clones.cloneDeterministic(_implementation, keccak256(abi.encodePacked(
_merkleTreeIPFSRef,
_root,
_startTime,
Expand Down Expand Up @@ -92,6 +81,7 @@ contract HATAirdropFactory is Ownable {
}

function predictHATAirdropAddress(
address _implementation,
string memory _merkleTreeIPFSRef,
bytes32 _root,
uint256 _startTime,
Expand All @@ -101,7 +91,7 @@ contract HATAirdropFactory is Ownable {
IERC20 _token,
ITokenLockFactory _tokenLockFactory
) external view returns (address) {
return Clones.predictDeterministicAddress(implementation, keccak256(abi.encodePacked(
return Clones.predictDeterministicAddress(_implementation, keccak256(abi.encodePacked(
_merkleTreeIPFSRef,
_root,
_startTime,
Expand Down
55 changes: 4 additions & 51 deletions docs/dodoc/tge/HATAirdropFactory.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
### createHATAirdrop

```solidity
function createHATAirdrop(string _merkleTreeIPFSRef, bytes32 _root, uint256 _startTime, uint256 _deadline, uint256 _lockEndTime, uint256 _periods, uint256 _totalAmount, contract IERC20Upgradeable _token, contract ITokenLockFactory _tokenLockFactory) external nonpayable returns (address result)
function createHATAirdrop(address _implementation, string _merkleTreeIPFSRef, bytes32 _root, uint256 _startTime, uint256 _deadline, uint256 _lockEndTime, uint256 _periods, uint256 _totalAmount, contract IERC20Upgradeable _token, contract ITokenLockFactory _tokenLockFactory) external nonpayable returns (address result)
```


Expand All @@ -24,6 +24,7 @@ function createHATAirdrop(string _merkleTreeIPFSRef, bytes32 _root, uint256 _sta

| Name | Type | Description |
|---|---|---|
| _implementation | address | undefined |
| _merkleTreeIPFSRef | string | undefined |
| _root | bytes32 | undefined |
| _startTime | uint256 | undefined |
Expand All @@ -40,23 +41,6 @@ function createHATAirdrop(string _merkleTreeIPFSRef, bytes32 _root, uint256 _sta
|---|---|---|
| result | address | undefined |

### implementation

```solidity
function implementation() external view returns (address)
```






#### Returns

| Name | Type | Description |
|---|---|---|
| _0 | address | undefined |

### owner

```solidity
Expand All @@ -77,7 +61,7 @@ function owner() external view returns (address)
### predictHATAirdropAddress

```solidity
function predictHATAirdropAddress(string _merkleTreeIPFSRef, bytes32 _root, uint256 _startTime, uint256 _deadline, uint256 _lockEndTime, uint256 _periods, contract IERC20 _token, contract ITokenLockFactory _tokenLockFactory) external view returns (address)
function predictHATAirdropAddress(address _implementation, string _merkleTreeIPFSRef, bytes32 _root, uint256 _startTime, uint256 _deadline, uint256 _lockEndTime, uint256 _periods, contract IERC20 _token, contract ITokenLockFactory _tokenLockFactory) external view returns (address)
```


Expand All @@ -88,6 +72,7 @@ function predictHATAirdropAddress(string _merkleTreeIPFSRef, bytes32 _root, uint

| Name | Type | Description |
|---|---|---|
| _implementation | address | undefined |
| _merkleTreeIPFSRef | string | undefined |
| _root | bytes32 | undefined |
| _startTime | uint256 | undefined |
Expand Down Expand Up @@ -130,22 +115,6 @@ function transferOwnership(address newOwner) external nonpayable
|---|---|---|
| newOwner | address | undefined |

### updateImplementation

```solidity
function updateImplementation(address _newImplementation) external nonpayable
```





#### Parameters

| Name | Type | Description |
|---|---|---|
| _newImplementation | address | undefined |

### withdrawTokens

```solidity
Expand Down Expand Up @@ -192,22 +161,6 @@ event HATAirdropCreated(address indexed _hatAirdrop, string _merkleTreeIPFSRef,
| _token | contract IERC20Upgradeable | undefined |
| _tokenLockFactory | contract ITokenLockFactory | undefined |

### ImplementationUpdated

```solidity
event ImplementationUpdated(address indexed _newImplementation)
```





#### Parameters

| Name | Type | Description |
|---|---|---|
| _newImplementation `indexed` | address | undefined |

### OwnershipTransferred

```solidity
Expand Down
25 changes: 4 additions & 21 deletions test/tge/hatairdrop.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ contract("HATAirdrop", (accounts) => {
periods = 90;

hatAirdropImplementation = await HATAirdrop.new();
hatAirdropFactory = await HATAirdropFactory.new(hatAirdropImplementation.address);
hatAirdropFactory = await HATAirdropFactory.new();

let airdropAddress = await hatAirdropFactory.predictHATAirdropAddress(
hatAirdropImplementation.address,
"QmSUXfYsk9HgrMBa7tgp3MBm8FGwDF9hnVaR9C1PMoFdS3",
merkleTree.getHexRoot(),
startTime,
Expand All @@ -74,6 +75,7 @@ contract("HATAirdrop", (accounts) => {
);

let tx = await hatAirdropFactory.createHATAirdrop(
hatAirdropImplementation.address,
"QmSUXfYsk9HgrMBa7tgp3MBm8FGwDF9hnVaR9C1PMoFdS3",
merkleTree.getHexRoot(),
startTime,
Expand Down Expand Up @@ -101,31 +103,12 @@ contract("HATAirdrop", (accounts) => {
await token.mint(hatAirdropFactory.address, totalAmount);
}

it("Update implementation", async () => {
await setupHATAirdrop();

await assertFunctionRaisesException(
hatAirdropFactory.updateImplementation(
accounts[3],
{ from: accounts[1] }
),
"Ownable: caller is not the owner"
);

assert.equal(await hatAirdropFactory.implementation(), hatAirdropImplementation.address);

let tx = await hatAirdropFactory.updateImplementation(accounts[3]);
assert.equal(tx.logs[0].event, "ImplementationUpdated");
assert.equal(tx.logs[0].args._newImplementation, accounts[3]);

assert.equal(await hatAirdropFactory.implementation(), accounts[3]);
});

it("Only owner can create airdrops", async () => {
await setupHATAirdrop();

await assertFunctionRaisesException(
hatAirdropFactory.createHATAirdrop(
hatAirdropImplementation.address,
"QmSUXfYsk9HgrMBa7tgp3MBm8FGwDF9hnVaR9C1PMoFdS3",
merkleTree.getHexRoot(),
startTime,
Expand Down

0 comments on commit c6e2993

Please sign in to comment.