-
Notifications
You must be signed in to change notification settings - Fork 31
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
31 changed files
with
3,379 additions
and
13 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
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 @@ | ||
book/ |
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,13 @@ | ||
table { | ||
margin: 0 auto; | ||
border-collapse: collapse; | ||
width: 100%; | ||
} | ||
|
||
table td:first-child { | ||
width: 15%; | ||
} | ||
|
||
table td:nth-child(2) { | ||
width: 25%; | ||
} |
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,11 @@ | ||
[book] | ||
src = "src" | ||
title = "" | ||
|
||
[output.html] | ||
no-section-label = true | ||
additional-js = ["solidity.min.js"] | ||
additional-css = ["book.css"] | ||
|
||
[output.html.fold] | ||
enable = true |
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,74 @@ | ||
hljs.registerLanguage("solidity",(()=>{"use strict";function e(){try{return!0 | ||
}catch(e){return!1}} | ||
var a=/-?(\b0[xX]([a-fA-F0-9]_?)*[a-fA-F0-9]|(\b[1-9](_?\d)*(\.((\d_?)*\d)?)?|\.\d(_?\d)*)([eE][-+]?\d(_?\d)*)?|\b0)(?!\w|\$)/ | ||
;e()&&(a=a.source.replace(/\\b/g,"(?<!\\$)\\b"));var s={className:"number", | ||
begin:a,relevance:0},n={ | ||
keyword:"assembly let function if switch case default for leave break continue u256 jump jumpi stop return revert selfdestruct invalid", | ||
built_in:"add sub mul div sdiv mod smod exp not lt gt slt sgt eq iszero and or xor byte shl shr sar addmod mulmod signextend keccak256 pc pop dup1 dup2 dup3 dup4 dup5 dup6 dup7 dup8 dup9 dup10 dup11 dup12 dup13 dup14 dup15 dup16 swap1 swap2 swap3 swap4 swap5 swap6 swap7 swap8 swap9 swap10 swap11 swap12 swap13 swap14 swap15 swap16 mload mstore mstore8 sload sstore msize gas address balance selfbalance caller callvalue calldataload calldatasize calldatacopy codesize codecopy extcodesize extcodecopy returndatasize returndatacopy extcodehash create create2 call callcode delegatecall staticcall log0 log1 log2 log3 log4 chainid origin gasprice basefee blockhash coinbase timestamp number difficulty gaslimit", | ||
literal:"true false"},i={className:"string", | ||
begin:/\bhex'(([0-9a-fA-F]{2}_?)*[0-9a-fA-F]{2})?'/},t={className:"string", | ||
begin:/\bhex"(([0-9a-fA-F]{2}_?)*[0-9a-fA-F]{2})?"/};function r(e){ | ||
return e.inherit(e.APOS_STRING_MODE,{begin:/(\bunicode)?'/})}function l(e){ | ||
return e.inherit(e.QUOTE_STRING_MODE,{begin:/(\bunicode)?"/})}var o={ | ||
SOL_ASSEMBLY_KEYWORDS:n,baseAssembly:e=>{ | ||
var a=r(e),o=l(e),c=/[A-Za-z_$][A-Za-z_$0-9.]*/,d=e.inherit(e.TITLE_MODE,{ | ||
begin:/[A-Za-z$_][0-9A-Za-z$_]*/,lexemes:c,keywords:n}),u={className:"params", | ||
begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,lexemes:c,keywords:n, | ||
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,o,s]},_={ | ||
className:"operator",begin:/:=|->/};return{keywords:n,lexemes:c, | ||
contains:[a,o,i,t,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s,_,{ | ||
className:"function",lexemes:c,beginKeywords:"function",end:"{",excludeEnd:!0, | ||
contains:[d,u,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,_]}]}}, | ||
solAposStringMode:r,solQuoteStringMode:l,HEX_APOS_STRING_MODE:i, | ||
HEX_QUOTE_STRING_MODE:t,SOL_NUMBER:s,isNegativeLookbehindAvailable:e} | ||
;const{baseAssembly:c,solAposStringMode:d,solQuoteStringMode:u,HEX_APOS_STRING_MODE:_,HEX_QUOTE_STRING_MODE:m,SOL_NUMBER:b,isNegativeLookbehindAvailable:E}=o | ||
;return e=>{for(var a=d(e),s=u(e),n=[],i=0;i<32;i++)n[i]=i+1 | ||
;var t=n.map((e=>8*e)),r=[];for(i=0;i<=80;i++)r[i]=i | ||
;var l=n.map((e=>"bytes"+e)).join(" ")+" ",o=t.map((e=>"uint"+e)).join(" ")+" ",g=t.map((e=>"int"+e)).join(" ")+" ",M=[].concat.apply([],t.map((e=>r.map((a=>e+"x"+a))))),p={ | ||
keyword:"var bool string int uint "+g+o+"byte bytes "+l+"fixed ufixed "+M.map((e=>"fixed"+e)).join(" ")+" "+M.map((e=>"ufixed"+e)).join(" ")+" enum struct mapping address new delete if else for while continue break return throw emit try catch revert unchecked _ function modifier event constructor fallback receive error virtual override constant immutable anonymous indexed storage memory calldata external public internal payable pure view private returns import from as using pragma contract interface library is abstract type assembly", | ||
literal:"true false wei gwei szabo finney ether seconds minutes hours days weeks years", | ||
built_in:"self this super selfdestruct suicide now msg block tx abi blockhash gasleft assert require Error Panic sha3 sha256 keccak256 ripemd160 ecrecover addmod mulmod log0 log1 log2 log3 log4" | ||
},O={className:"operator",begin:/[+\-!~*\/%<>&^|=]/ | ||
},C=/[A-Za-z_$][A-Za-z_$0-9]*/,N={className:"params",begin:/\(/,end:/\)/, | ||
excludeBegin:!0,excludeEnd:!0,lexemes:C,keywords:p, | ||
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,s,b,"self"]},f={ | ||
begin:/\.\s*/,end:/[^A-Za-z0-9$_\.]/,excludeBegin:!0,excludeEnd:!0,keywords:{ | ||
built_in:"gas value selector address length push pop send transfer call callcode delegatecall staticcall balance code codehash wrap unwrap name creationCode runtimeCode interfaceId min max" | ||
},relevance:2},y=e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/, | ||
lexemes:C,keywords:p}),w={className:"built_in", | ||
begin:(E()?"(?<!\\$)\\b":"\\b")+"(gas|value|salt)(?=:)"};function x(e,a){return{ | ||
begin:(E()?"(?<!\\$)\\b":"\\b")+e+"\\.\\s*",end:/[^A-Za-z0-9$_\.]/, | ||
excludeBegin:!1,excludeEnd:!0,lexemes:C,keywords:{built_in:e+" "+a}, | ||
contains:[f],relevance:10}}var h=c(e),v=e.inherit(h,{ | ||
contains:h.contains.concat([{begin:/\./,end:/[^A-Za-z0-9$.]/,excludeBegin:!0, | ||
excludeEnd:!0,keywords:{built_in:"slot offset length address selector"}, | ||
relevance:2},{begin:/_/,end:/[^A-Za-z0-9$.]/,excludeBegin:!0,excludeEnd:!0, | ||
keywords:{built_in:"slot offset"},relevance:2}])});return{aliases:["sol"], | ||
keywords:p,lexemes:C, | ||
contains:[a,s,_,m,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,b,w,O,{ | ||
className:"function",lexemes:C, | ||
beginKeywords:"function modifier event constructor fallback receive error", | ||
end:/[{;]/,excludeEnd:!0, | ||
contains:[y,N,w,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:/%/ | ||
},x("msg","gas value data sender sig"),x("block","blockhash coinbase difficulty gaslimit basefee number timestamp chainid"),x("tx","gasprice origin"),x("abi","decode encode encodePacked encodeWithSelector encodeWithSignature encodeCall"),x("bytes","concat"),f,{ | ||
className:"class",lexemes:C,beginKeywords:"contract interface library",end:"{", | ||
excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{beginKeywords:"is",lexemes:C | ||
},y,N,w,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{lexemes:C, | ||
beginKeywords:"struct enum",end:"{",excludeEnd:!0,illegal:/[:"\[\]]/, | ||
contains:[y,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{ | ||
beginKeywords:"import",end:";",lexemes:C,keywords:"import from as", | ||
contains:[y,a,s,_,m,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,O]},{ | ||
beginKeywords:"using",end:";",lexemes:C,keywords:"using for", | ||
contains:[y,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,O]},{className:"meta", | ||
beginKeywords:"pragma",end:";",lexemes:C,keywords:{ | ||
keyword:"pragma solidity experimental abicoder", | ||
built_in:"ABIEncoderV2 SMTChecker v1 v2"}, | ||
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.inherit(a,{ | ||
className:"meta-string"}),e.inherit(s,{className:"meta-string"})]},{ | ||
beginKeywords:"assembly",end:/\b\B/, | ||
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.inherit(v,{begin:"{", | ||
end:"}",endsParent:!0,contains:v.contains.concat([e.inherit(v,{begin:"{", | ||
end:"}",contains:v.contains.concat(["self"])})])})]}],illegal:/#/}}})()); | ||
|
||
// Ugly hack to reload HLJS | ||
hljs.initHighlightingOnLoad(); |
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,185 @@ | ||
# Tapio Protocol | ||
|
||
Tapio is a liquidity aggregator that acts as the middle layer between self-pegging assets and downstream DeFi | ||
applications. Liquidity is a cornerstone of DeFi and represents the most significant use case for self-pegging assets | ||
when paired with complementary tokens. However, once these assets are utilized in liquidity pools and the resulting LP | ||
token is obtained, the journey often stalls, leaving limited options for further use. Additionally, the ecosystem faces | ||
heavy fragmentation of self-pegging asset liquidity, with individual protocols employing distinct reward mechanisms, | ||
token models, and architectures—resulting in an increasingly fragmented and inefficient landscape. | ||
|
||
Introducing the Tapio LP Token—the first utility-focused LP token designed for the self-pegging asset ecosystem. Serving | ||
as both a liquidity aggregator and an arbitrage hub, it fundamentally operates as a rebasing LP token that represents | ||
diverse stable pools within Tapio Finance. These pools include pairings between self-pegging assets and their | ||
complements, such as: | ||
|
||
- stETH-ETH | ||
- USDT-USDC | ||
- rETH-wstETH | ||
|
||
Unlike traditional liquidity pools in DEXs, the Tapio LP Token you receive after depositing assets is pegged to the | ||
underlying assets and can be seamlessly used within DeFi or as a medium of exchange, just like any other asset. The | ||
Tapio LP Token also accrues underlying token rewards and fees generated by the pools—such as swaps, redemptions, and | ||
more—delivering an attractive real yield APR even before engaging in further DeFi activities. | ||
|
||
For added flexibility, the Tapio LP Token can be wrapped into a wrapped LP token, adopting an "interest rate" model that | ||
simplifies integration and cross-chain usage. | ||
|
||
As a synthetic asset protocol, Tapio Finance dynamically adjusts the pricing curves of self-pegging asset pools, | ||
enabling efficient swaps and arbitrage opportunities. This ensures the stability of tapETH while unlocking excellent use | ||
cases for Tapio's liquidity pools. | ||
|
||
## Overview | ||
|
||
In Tapio, users can: | ||
|
||
- Create new AMM pools using Factory. | ||
- Mint, swap and redeem tokens in pools. | ||
- Wrap and unwrap LP tokens. | ||
|
||
The protocol is built using modular, upgradeable components and is based on CurveFi's StableSwap algorithm. This design | ||
ensuring the system can adapt and scale with evolving protocol requirements. | ||
|
||
## Contracts | ||
|
||
Tapio uses several core contracts to facilitate management of pools and it's functionality: | ||
|
||
### SelfPeggingAssetFactory | ||
|
||
The SelfPeggingAssetFactory contract automates the deployment of new pools, simplifying their creation and management. | ||
All pools deployed through the Factory are governed by Pike's governance system. | ||
|
||
### SelfPeggingAsset | ||
|
||
The SelfPeggingAsset conttract represents a AMM pool. It allows users to swap, mint and redeem tokens of the pool. It | ||
implements the StableSwap algorithm. | ||
|
||
### LPToken | ||
|
||
The LPToken is an ERC20 rebase token issued by StableSwap pools to liquidity providers. | ||
|
||
LPToken balances are dynamic and reflect the holder's share of the total LPToken supply managed by the protocol. Since | ||
account shares are not normalized, the contract tracks the total sum of all shares to compute each account's token | ||
balance using the formula: | ||
|
||
``` | ||
shares[account] * _totalSupply / _totalShares | ||
``` | ||
|
||
Here, \_totalSupply represents the total amount of LPToken managed by the protocol. | ||
|
||
### WLPToken | ||
|
||
The WLPToken is an ERC4626 standard token that represents an account's share of the total LPToken supply. Unlike | ||
LPToken, which dynamically updates balances based on staking rewards and swap fees, WLPToken balances only change during | ||
transfers. | ||
|
||
Designed as a "power user" token, WLPToken caters to DeFi protocols that do not support rebasable tokens. The contract | ||
serves as a trustless wrapper, accepting LPToken and minting WLPToken in return. When users choose to unwrap, the | ||
contract burns their WLPToken and returns the corresponding locked LPToken. | ||
|
||
## Usage | ||
|
||
This is a list of the most frequently needed commands. | ||
|
||
### Build | ||
|
||
Build the contracts: | ||
|
||
```sh | ||
$ forge build | ||
``` | ||
|
||
### Clean | ||
|
||
Delete the build artifacts and cache directories: | ||
|
||
```sh | ||
$ forge clean | ||
``` | ||
|
||
### Compile | ||
|
||
Compile the contracts: | ||
|
||
```sh | ||
$ forge build | ||
``` | ||
|
||
### Coverage | ||
|
||
Get a test coverage report: | ||
|
||
```sh | ||
$ forge coverage | ||
``` | ||
|
||
### Deploy to Testnet | ||
|
||
Deploy to Base Testnet: | ||
|
||
```sh | ||
$ forge script ./script/Testnet.s.sol -vvv --rpc-url basesepolia --broadcast | ||
``` | ||
|
||
Before deploying make sure you configure the neccessary variables in `.env` file. To just test the scripts with just a | ||
dry run remove the `--broadcast` flag. | ||
|
||
### Verifying Contracts on Testnet Explorer | ||
|
||
Here is an example on how to verify a contract on base sepolia: | ||
|
||
```sh | ||
$ forge verify-contract <contract-address> <contract-name> --watch --etherscan-api-key <basescan-api-key> --chain-id 84532 --constructor-args <encoded-constructor-args> | ||
``` | ||
|
||
You can find the contract name and constructor args in the broadcast directory. To encode the constructor args you can | ||
use: https://abi.hashex.org/ | ||
|
||
### Format | ||
|
||
Format the contracts: | ||
|
||
```sh | ||
$ forge fmt | ||
``` | ||
|
||
### Gas Usage | ||
|
||
Get a gas report: | ||
|
||
```sh | ||
$ forge test --gas-report | ||
``` | ||
|
||
### Lint | ||
|
||
Lint the contracts: | ||
|
||
```sh | ||
$ yarn run lint | ||
``` | ||
|
||
### Test | ||
|
||
Run the tests: | ||
|
||
```sh | ||
$ forge test | ||
``` | ||
|
||
Generate test coverage and output result to the terminal: | ||
|
||
```sh | ||
$ yarn run test:coverage | ||
``` | ||
|
||
Generate test coverage with lcov report (you'll have to open the `./coverage/index.html` file in your browser, to do so | ||
simply copy paste the path): | ||
|
||
```sh | ||
$ yarn run test:coverage:report | ||
``` | ||
|
||
## License | ||
|
||
This project is licensed under MIT. |
Oops, something went wrong.