-
Notifications
You must be signed in to change notification settings - Fork 0
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
16 changed files
with
596 additions
and
133 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
BASE_RPC= | ||
OWNER_PRIVATE_KEY= | ||
ETHERSCAN_API_KEY= |
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 |
---|---|---|
@@ -1,34 +1,25 @@ | ||
name: test | ||
name: CI | ||
|
||
on: workflow_dispatch | ||
|
||
env: | ||
FOUNDRY_PROFILE: ci | ||
on: | ||
push: | ||
branches: | ||
- main | ||
pull_request: | ||
branches: | ||
- main | ||
|
||
jobs: | ||
check: | ||
strategy: | ||
fail-fast: true | ||
|
||
name: Foundry project | ||
build-and-test: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
with: | ||
submodules: recursive | ||
|
||
- name: Install Foundry | ||
uses: foundry-rs/foundry-toolchain@v1 | ||
with: | ||
version: nightly | ||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v2 | ||
|
||
- name: Run Forge build | ||
run: | | ||
forge --version | ||
forge build --sizes | ||
id: build | ||
- name: Install Foundry | ||
uses: foundry-rs/foundry-toolchain@v1 | ||
with: | ||
version: nightly | ||
|
||
- name: Run Forge tests | ||
run: | | ||
forge test -vvv | ||
id: test | ||
- name: Run make test | ||
run: make test |
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,6 @@ | ||
[submodule "lib/forge-std"] | ||
path = lib/forge-std | ||
url = https://github.com/foundry-rs/forge-std | ||
[submodule "lib/openzeppelin-contracts"] | ||
path = lib/openzeppelin-contracts | ||
url = https://github.com/OpenZeppelin/openzeppelin-contracts |
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,23 @@ | ||
-include .env | ||
|
||
.PHONY: install | ||
install: | ||
@foundryup | ||
@forge install OpenZeppelin/openzeppelin-contracts --no-commit | ||
|
||
.PHONY: test | ||
test: | ||
@forge test -vvvv | ||
|
||
.PHONY: deploy | ||
deploy: | ||
@echo "Deploying to Base Mainnet" | ||
@forge script script/Deploy.s.sol --rpc-url $(BASE_RPC) --private-key $(OWNER_PRIVATE_KEY) --broadcast --verify --etherscan-api-key $(ETHERSCAN_API_KEY) -vvvv | ||
|
||
.PHONY: build | ||
build: | ||
@forge build | ||
|
||
.PHONY: format | ||
format: | ||
@forge fmt |
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 |
---|---|---|
@@ -1,66 +1,21 @@ | ||
## Foundry | ||
## Friendly Agent | ||
|
||
**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** | ||
Helps to make limit orders within a single transaction on Friendtech. Some additional helpers added to withdraw ETH/Arbitrary ERC20s. | ||
|
||
Foundry consists of: | ||
Create `.env` file from `.env.example` and fill in the details. | ||
|
||
- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). | ||
- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. | ||
- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. | ||
- **Chisel**: Fast, utilitarian, and verbose solidity REPL. | ||
## Install | ||
|
||
## Documentation | ||
`make install` | ||
|
||
https://book.getfoundry.sh/ | ||
## Tests | ||
|
||
## Usage | ||
`make test` | ||
|
||
### Build | ||
## Fork Tests | ||
|
||
```shell | ||
$ forge build | ||
``` | ||
`make test-fork` | ||
|
||
### Test | ||
## Deploy | ||
|
||
```shell | ||
$ forge test | ||
``` | ||
|
||
### Format | ||
|
||
```shell | ||
$ forge fmt | ||
``` | ||
|
||
### Gas Snapshots | ||
|
||
```shell | ||
$ forge snapshot | ||
``` | ||
|
||
### Anvil | ||
|
||
```shell | ||
$ anvil | ||
``` | ||
|
||
### Deploy | ||
|
||
```shell | ||
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key> | ||
``` | ||
|
||
### Cast | ||
|
||
```shell | ||
$ cast <subcommand> | ||
``` | ||
|
||
### Help | ||
|
||
```shell | ||
$ forge --help | ||
$ anvil --help | ||
$ cast --help | ||
``` | ||
`make deploy` |
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
Submodule openzeppelin-contracts
added at
fd81a9
This file was deleted.
Oops, something went wrong.
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,20 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.18; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
import {FriendlyAgent} from "../src/FriendlyAgent.sol"; | ||
import {HelperConfig} from "./HelperConfig.s.sol"; | ||
|
||
contract DeployFriendlyAgent is Script { | ||
function run() external returns (FriendlyAgent) { | ||
uint256 ownerPrivateKey = vm.envUint("OWNER_PRIVATE_KEY"); | ||
HelperConfig helperConfig = new HelperConfig(); | ||
|
||
vm.startBroadcast(ownerPrivateKey); | ||
FriendlyAgent friendlyAgent = new FriendlyAgent(helperConfig.friendsTechAddress()); | ||
vm.stopBroadcast(); | ||
|
||
return friendlyAgent; | ||
} | ||
} |
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,39 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.18; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
import {FriendtechSharesV1} from "../src/FriendtechSharesV1.sol"; | ||
|
||
contract HelperConfig is Script { | ||
address public friendsTechAddress; | ||
|
||
constructor() { | ||
if (block.chainid == 8453) { | ||
friendsTechAddress = getBaseMainnet(); | ||
} else { | ||
friendsTechAddress = getOrCreateAnvilConfig(); | ||
} | ||
} | ||
|
||
function getOrCreateAnvilConfig() public returns (address) { | ||
if (friendsTechAddress != address(0)) { | ||
return friendsTechAddress; | ||
} | ||
|
||
vm.startBroadcast(); | ||
FriendtechSharesV1 friendTechSharesV1 = new FriendtechSharesV1(); | ||
friendTechSharesV1.setSubjectFeePercent(0); | ||
friendTechSharesV1.setProtocolFeePercent(0); | ||
|
||
// Set to burn address for tests | ||
friendTechSharesV1.setFeeDestination(0x0000000000000000000000000000000000000000); | ||
vm.stopBroadcast(); | ||
|
||
return address(friendTechSharesV1); | ||
} | ||
|
||
function getBaseMainnet() public pure returns (address) { | ||
return 0xCF205808Ed36593aa40a44F10c7f7C2F67d4A4d4; | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
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,81 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.18; | ||
|
||
interface IFriendtechSharesV1 { | ||
function getBuyPriceAfterFee(address sharesSubject, uint256 amount) external view returns (uint256); | ||
function getSellPriceAfterFee(address sharesSubject, uint256 amount) external view returns (uint256); | ||
function buyShares(address sharesSubject, uint256 amount) external payable; | ||
function sellShares(address sharesSubject, uint256 amount) external payable; | ||
} | ||
|
||
interface IERC20 { | ||
function transfer(address recipient, uint256 amount) external returns (bool); | ||
function balanceOf(address account) external view returns (uint256); | ||
} | ||
|
||
contract FriendlyAgent { | ||
error FriendlyAgent__NotOwner(); | ||
error FriendlyAgent__AmountGreaterThanHoldings(); | ||
error FriendlyAgent__OverMaxLimit(); | ||
error FriendlyAgent__UnderMinLimit(); | ||
|
||
IFriendtechSharesV1 public immutable i_friendtechShares; | ||
address public immutable i_owner; | ||
mapping(address => uint256) private s_holdings; | ||
|
||
constructor(address _friendtechSharesAddress) { | ||
i_friendtechShares = IFriendtechSharesV1(_friendtechSharesAddress); | ||
i_owner = msg.sender; | ||
} | ||
|
||
modifier onlyOwner() { | ||
if (msg.sender != i_owner) { | ||
revert FriendlyAgent__NotOwner(); | ||
} | ||
_; | ||
} | ||
|
||
function buyShares(uint256 maxPrice, uint256 amount, address sharesSubject) public payable onlyOwner { | ||
uint256 priceAfterFee = i_friendtechShares.getBuyPriceAfterFee(sharesSubject, amount); | ||
if (priceAfterFee > maxPrice) { | ||
revert FriendlyAgent__OverMaxLimit(); | ||
} | ||
|
||
s_holdings[sharesSubject] += amount; | ||
i_friendtechShares.buyShares{value: priceAfterFee}(sharesSubject, amount); | ||
} | ||
|
||
function sellShares(uint256 minPrice, uint256 amount, address sharesSubject) public onlyOwner { | ||
if (s_holdings[sharesSubject] < amount) { | ||
revert FriendlyAgent__AmountGreaterThanHoldings(); | ||
} | ||
uint256 priceAfterFee = i_friendtechShares.getSellPriceAfterFee(sharesSubject, amount); | ||
if (priceAfterFee < minPrice) { | ||
revert FriendlyAgent__UnderMinLimit(); | ||
} | ||
|
||
s_holdings[sharesSubject] -= amount; | ||
i_friendtechShares.sellShares{value: 0}(sharesSubject, amount); | ||
} | ||
|
||
function withdraw() public onlyOwner { | ||
(bool callSuccess,) = payable(i_owner).call{value: address(this).balance}(""); | ||
require(callSuccess, "Call failed"); | ||
} | ||
|
||
function withdrawToken(address tokenAddress) public onlyOwner { | ||
IERC20 token = IERC20(tokenAddress); | ||
uint256 balance = token.balanceOf(address(this)); | ||
require(balance > 0, "No tokens to withdraw"); | ||
require(token.transfer(i_owner, balance), "Token transfer failed"); | ||
} | ||
|
||
function getHoldings(address sharesSubject) external view returns (uint256) { | ||
return s_holdings[sharesSubject]; | ||
} | ||
|
||
fallback() external payable {} | ||
|
||
receive() external payable {} | ||
} |
Oops, something went wrong.