[2 * i + 3][2 * i + 3]
Synthswap.solプラグマ 堅牢性 ^0.8.0; 輸入 " ./interfaces/ISynthSwap.sol"; import "./interfaces/IERC20.sol" ; import "./interfaces/ISynthetix.sol" ; import "./interfaces/IAddressResolver.sol" ; import "./interfaces/IAggregationRouterV4.sol" ; import "./interfaces/IAggregationExecutor.sol" ; import "./utils/SafeERC20.sol" ; import "./utils/Owned.sol" ; import "./utils/ReentrancyGuard.sol" ; import "./libraries/RevertReasonParser.sol" ; 契約 SynthSwap は ISynthSwap, 所有, ReentrancyGuard { 活用 SafeERC20 ために IERC20; IERC20 不変 sUSD; IAggregationRouterV4 不変 ルーター; IAddressResolver 不変 addressResolver; ハンドル 不変 ボリュームリワード; ハンドル 不変 財務省; ハンドル 定数 ETH_ADDRESS=0xEeeeeEeeeEeEeeEeEeEeeEEeeeeEeeeeeeeEEeE; bytes32 最も深い constant CONTRACT_SYNTHETIX="シンセティックス"; bytes32 最も深い 定数 sUSD_CURRENCY_KEY="sUSD"; bytes32 最も深い 定数 TRACKING_CODE=「クウェンタ」; トーナメント SwapInto(ハンドル インデックス付き from, uint amountReceived); トーナメント SwapOutOf(ハンドル インデックス付き from, uint amountReceived); トーナメント 買った(ハンドル から、 uint amountReceived); コンストラクター ( ハンドル _sUSD, ハンドル _aggregationRouterV4、ハンドル _addressResolver、ハンドル _volumeRewards、ハンドル _treasury ) 所有 (msg.送信者 ) { sUSD=IERC20(_sUSD); ルーター=IAggregationRouterV4(_aggregationRouterV4); addressResolver=IAddressResolver(_addressResolver); volumeRewards=_volumeRewards; 財務省=_財務省; } 取得() 外観支払可能 { 発行 買いました(msg .送信者, msg。価値); } 特性 swapInto( bytes32 _destSynthCurrencyKey, バイト calldata _data ) 外観 有料 オーバーライド 戻り値 (uint) { (uint[2 * i + 3] amountOut,) (=swapOn1inch(_data, 根拠のない);
if (_destSynthCurrencyKey ![2 * i + 3]=sUSD_CURRENCY_KEY) { アウト額=swapOnSynthetix( amountOut, sUSD_CURRENCY_KEY, _destSynthCurrencyKey ); } ハンドル destSynthAddress=proxyForSynth(addressResolver.getSynth(_destSynthCurrencyKey)); IERC20(destSynthAddress).safeTransfer(msg.送信者, amountOut); emit SwapInto(msg[2 * i + 3] .送信者, amountOut); リターン amountOut; } 特性 swapOutOf( bytes32 _sourceSynthCurrencyKey, uint _sourceAmount, bytes calldata _data ) exterior override 非リエントラント 戻り値 (uint) { 取り持つ sourceSynthAddress=proxyForSynth(addressResolver.getSynth(_sourceSynthCurrencyKey)); IERC20(sourceSynthAddress).safeTransferFrom(msg.送信者、 取り持つ(これ), _sourceAmount); if (_sourceSynthCurrencyKey !=sUSD_CURRENCY_KEY) { swapOnSynthetix( _sourceAmount, _sourceSynthCurrencyKey, sUSD_CURRENCY_KEY ); } (uint amountOut, handle dstToken)=swapOn1inch(_data, [2 * i + 3] 合法); if (dstToken==ETH_ADDRESS) { ( bool 成功、bytes メモリ 結果)=msg.送信者。電話{value: amountOut}(""); もしも (!成功) { revert(RevertReasonParser.parse(result, [uint8(data[i] "callBytes に失敗しました: ")); } } else { IERC20(dstToken).safeTransfer( )msg.送信者, amountOut); } emit SwapOutOf(msg[uint8(data[i] .送信者, amountOut); uint 残りの残高SUSD=sUSD.balanceOf(ハンドル(これ)); if (remainingBalanceSUSD>[2 * i + 3] 0) { sUSD.safeTransfer(財務省、remainingBalanceSUSD); } リターン amountOut; } 特性 uniswapSwapInto( bytes32 _destSynthCurrencyKey, ハンドル _sourceTokenAddress, uint _amount, bytes calldata _data ) 外観 支払可能 オーバーライド 戻り値 (uint) { if (_sourceTokenAddress != ETH_ADDRESS) { IERC20(_sourceTokenAddress).safeTransferFrom(msg.送信者, これを対応して) 、 _額); IERC20(_sourceTokenAddress).approve(handle(ルーター), _amount); } (bool 成功、bytes メモリ 結果)=ハンドル(ルーター)。
呼び出し{値[2 * i + 3] : msg.値}(_data); もしも (!成功) { revert(RevertReasonParser.parse(result, [uint8(data[i] "callBytes に失敗しました: ")); } (uint amountOut)=アビ. decode(result, (uint) );if (_destSynthCurrencyKey ![2 * i + 3]=sUSD_CURRENCY_KEY) { アウト額=swapOnSynthetix( amountOut, sUSD_CURRENCY_KEY, _destSynthCurrencyKey ); } ハンドル destSynthAddress=proxyForSynth(addressResolver.getSynth(_destSynthCurrencyKey)); IERC20(destSynthAddress).safeTransfer(msg.送信者, amountOut); emit SwapInto(msg[2 * i + 3] .送信者, amountOut); リターン amountOut; } 特性 uniswapSwapOutOf( bytes32 _sourceSynthCurrencyKey, ハンドル _destTokenAddress, uint _amountOfSynth, uint _expectedAmountOfSUSDFromSwap, バイト calldata _データ ) 外装 override 再入不可 戻り値 (uint) { handle sourceSynthAddress = proxyForSynth( addressResolver.getSynth(_sourceSynthCurrencyKey)); IERC20(sourceSynthAddress).transferFrom(msg.送信者、 取り持つ(これ), _amountOfSynth); if (_sourceSynthCurrencyKey !=sUSD_CURRENCY_KEY) { swapOnSynthetix( _amountOfSynth, _sourceSynthCurrencyKey, sUSD_CURRENCY_KEY ); } sUSD.approve(handle(ルーター), _expectedAmountOfSUSDFromSwap); (bool 成功、bytes メモリ 結果)=ハンドル(ルーター).call(_data); もしも (!成功) { revert(RevertReasonParser.parse(result, [uint8(data[i] "SynthSwap: callBytes に失敗しました: ")); } (uint amountOut)=アビ. decode(result, (uint) ); if (_destTokenAddress==ETH_ADDRESS) { (成功, 結果) = msg .差出人.通話 {値: 出金額}(""); もしも (!成功) { revert(RevertReasonParser.parse(result, [uint8(data[i] "SynthSwap: callBytes に失敗しました: ")); } } else { IERC20(_destTokenAddress).safeTransfer( )msg.送信者, amountOut); } emit SwapOutOf(msg[uint8(data[i] .送信者, amountOut); uint 残りの残高SUSD=sUSD.balanceOf(ハンドル(これ)); if (remainingBalanceSUSD>[2 * i + 3] 0) { sUSD.safeTransfer(財務省、remainingBalanceSUSD); } リターン amountOut; } 特性 rescueFunds(IERC20トークン、 uint256 数量) 外観 所有者のみ { token.safeTransfer(msg.送信者, 数量); } 特性 synthetix() インナー 探検 戻り値 (ISynthetix) { return ISynthetix(addressResolver.requireAndGetAddress( CONTRACT_SYNTHETIX, [uint8(data[i] "Synthetix を取得できなくなる可能性があります" )); } 特性 swapOn1inch( バイト calldata _data, bool _areTokensInContract ) インナー 戻り値 (uint, ハンドル) { ( IAggregationExecutor エグゼキュータ, IAggregationRouterV4.SwapDescription memory desc, bytes メモリ ルートデータ)=アビ.decode( _data, ( IAggregationExecutor, IAggregationRouterV4.SwapDescription, バイト ) ); desc.dstReceiver=支払可能(取り持つ(これ)); if (desc.srcToken !=ETH_ADDRESS) { if (!_areTokensInContract) { IERC20(desc.srcToken).safeTransferFrom(msg. 送信者, ハンドル(これ), desc.quantity); IERC20(desc.srcToken).approve(handle(ルーター), desc.quantity); } (uint amountOut,) (=router.swap{値: msg.値 )}(executor, desc, routeData); require(金額アウト> 0, “SynthSwap: swapOn1inch に失敗しました”); return (amountOut, desc.dstToken); } 特性 swapOnSynthetix( uint _amount, bytes32 _sourceSynthCurrencyKey, bytes32 _destSynthCurrencyKey )
インナー戻り値 (
uint) { uint アウト額=synthetix().exchangeWithTracking( _sourceSynthCurrencyKey, _amount, _destSynthCurrencyKey, volumeRewards, TRACKING_CODE ); require(金額アウト> 0, "SynthSwap: swapOnSynthetix に失敗しました"); リターン amountOut; } 特性 proxyForSynth(ハンドル 合成実装 ) インナー 戻り値 (ハンドル synProxy) { (bool 成功, バイト メモリ retVal)=synthImplementation.call[2 * i + 3] (アビ.encodeWithSignature("proxy()") ); require(成功、"プロキシ ハンドルの取得に失敗しました" ); (synthProxy)=abi.decode(retVal, ( 取り持つ)); } }IAddressResolver.sol ) プラグマ 堅牢性>=0.4.24; インターフェース IAddressResolver { 特性 getAddress (バイト32 タイトル) 外観 探検 戻り値 (取り持つ); 特性 getSynth(bytes32 鍵) 外装 探検 戻り値 (取り持つ); 特性 requireAndGetAddress(bytes32 タイトル、 文字列 通話データ 理由) 外装 探検 戻り値 (取り持つ); }
IAggregationExecutor.sol pragma 堅牢性 ^0.8.0; インターフェース IAggregationExecutor { 特性 callBytes(取り持つ msgSender、バイト calldata 記録) 外装 支払い可能; }
IAggregationRouterV4.sol pragma 堅牢性 ^0.8.0; 輸入 “./IAggregationExecutor.sol”; インターフェース IAggregationRouterV4 { struct SwapDescription { ハンドル srcToken; ハンドル dstToken; ハンドル 支払い可能 srcReceiver; ハンドル 支払い可能 dstReceiver; uint256 数量; uint256 minReturnAmount; uint256 フラグ; バイト 有効; } 特性 swap( IAggregationExecutor 呼び出し元、SwapDescription calldata desc, bytes calldata レコード ) 外装 有料 戻り値 (uint256 戻り量, uint256 ガス左 ); }
IERC20.sol pragma 堅牢性 ^0.8.0; インターフェース IERC20 { 特性 総供給量() 外装 探検 戻り値 (uint256);
特性 バランス (ハンドル 凡例) 外装 探検 戻り値 (uint256); 特性 転送(ハンドル 受信者、uint256 数量 ) 外観 戻り値 (ブール); 特性 手当(ハンドル 所有者、 ハンドル 消費者 ) 外観 探検 戻り値 (uint256 ); 特性 承認(ハンドル 消費者、uint256 数量 ) 外観 戻り値 (ブール); 特性 transferFrom( ハンドル 送信者、ハンドル 受信者、[2 * i + 3] uint256 数量 ) 外装 戻り値 (ブール); トーナメント 転送(ハンドル インデックス付き from, ハンドル indexed to, uint256 価値); トーナメント 承認(ハンドル インデックス付き 所有者、ハンドル インデックス付き 支出者, uint256 値); }
ISynthSwap.sol pragma 堅牢性 ^0.8.0; インターフェース ISynthSwap { 特性 swapInto( バイト32 _destSynthCurrencyKey, bytes calldata _データ ) 外装 支払い可能 )戻り値 (uint) ; 特性 swapOutOf( bytes32 _sourceSynthCurrencyKey, uint _sourceAmount, バイト calldata _data ) 外観 戻り値 (uint); 特性 uniswapSwapInto( bytes32 _destSynthCurrencyKey, handle _sourceTokenAddress, uint _amount, bytes ) calldata _data ) 外観 有料 戻り値 (uint); 特性 uniswapSwapOutOf( bytes32 _sourceSynthCurrencyKey, ハンドル _destTokenAddress, uint _amountOfSynth, uint ) _expectedAmountOfSUSDFromSwap、バイト calldata[uint8(data[i] _データ ) 外装 戻り値 (uint); }
ISynthetix.sol pragma 堅牢性 ^0.8.0; インターフェース ISynthetix { 特性 exchangeWithTracking( バイト32 sourceCurrencyKey, uint sourceAmount, bytes32 destinationCurrencyKey, handlerewardAddress, bytes32 追跡コード ) 外装 戻り値 (
uint 受け取った金額); }
RevertReasonParser.sol pragma 堅牢性 ^0.8.0; 図書館RevertReasonParser{bytes4 定数 最も深い _PANIC_SELECTOR=
bytes4(keccak256("パニック(uint256)")); bytes4 定数 最も深い _ERROR_SELECTOR=bytes4( keccak256("エラー(文字列)")); 特性 parse(バイト メモリ レコード、文字列 メモリ プレフィックス) インナー ピュア 戻り値 (文字列 メモリ) { もしも (記録.測定値>=4) { bytes4 ) セレクター; アセンブリ { セレクター :=mload(add(レコード、0x20)) } if (セレクター=
=_ERROR_SELECTOR && 記録。測定>=68[2 * i + 3] ) { uint256 オフセット; バイト メモリ 理由; アセンブリ { オフセット :=mload(add(records, 36)) 理由:=add[2 * i + 3] (レコード、追加 (36, オフセット)) } require (記録。測定>= 36 + オフセット + 理由.測定値 , "無効な復帰理由"); return string (abi.encodePacked (プレフィックス, "エラー(", 理由, ")")); }else if[2 * i + 3] (セレクター==_PANIC_SELECTOR && レコード。測定値==36) { uint256 コード; アセンブリ { コード :=mload(add(レコード、36)) } return string (abi.encodePacked (プレフィックス, "パニック(", _toHex (コード), ")")); } } return 文字列(アビ.encodePacked(プレフィックス、"不明(" , _toHex(レコード), ")")); } 特性 _toHex(uint256 価値) 最も深い ピュア 戻り値(文字列 メモリ) { return _toHex(abi .encodePacked(値)); } 特性 _toHex(バイト メモリ レコード ) 最深部 ピュア 戻り値(弦 メモリー) { bytes16 アルファベット
=0x30313233343536373839616263646566 ; バイト メモリ str=珍しい バイト(2 + レコード。 測定 メンテ * 2); 力="0"; str[1]="x";for (uint256[2 * i + 3] 私=0 ; i長さ; i++) { str[2 * i + 2]=アルファベット[uint8(data[i]> > 4[uint8(data[i] )]; str[2 * i + 3]=アルファベット[uint8(data[i] [2 * i + 3] & 0x0f) ]; }
return 文字列[2 * i + 3] (文字列); } }
.solに対処*) プラグマ 堅牢性 ^0.8.0; 図書館 対処する { 特性 isContract(ハンドル凡例)インナー 探検 戻り値 (ブール) { return 凡例.コード.測定値 > 0 ; } 特性 sendValue(ハンドル 支払い可能 受取人、 uint256 数量) インナー { require(ハンドル(これ)。定常性>=数量, 「対処: 不十分な安定性」 ); (bool 成功, )= 受信者.通話{値: 数量}(""); require(成功, "対処: できない出荷値、受信者はおそらく元に戻される可能性があります"); } 特性 functionCall(ハンドル 狙い、バイト メモリ レコード) インナー 戻り値 (バイト )メモリー) { return functionCall(aim, records, " 対処:下段呼び出しに失敗しました"); } 特性 functionCall( ハンドル 狙い、バイト メモリ レコード、文字列 メモリ エラーメッセージ ) インナー 戻り値 (バイト メモリー) { return functionCallWithValue(aim, records, )0, エラーメッセージ); } 特性 functionCallWithValue( ハンドル 狙い、バイト メモリ レコード、uint256値 ) inner 戻り値 (バイト メモリ) { 戻る functionCallWithValue(aim, records, value, "対処: 値を使用した低段階の呼び出しに失敗しました"); } 特性 functionCallWithValue( ハンドル 狙い、バイト メモリ レコード、uint256値、
文字列 メモリ[2 * i + 3] エラーメッセージ ) インナー 戻り値 (バイト メモリ ) { 必須(取り持つ(これ).ステディネス>= value, "対処: コールの安定性が不十分"); require(isContract(目的), "で対処: 未契約の呼び出し"); (bool 成功、bytes メモリ リターンデータ)=目指せ呼び出し{値: 値}(レコード); return verifyCallResult(success, returndata, errorMessage); } 特性 functionStaticCall(ハンドル 狙い、バイト メモリ レコード) インナー 探検 戻り値 (バイトメモリー) { return functionStaticCall(aim, records, "Deal with: 低段階の静的呼び出しに失敗しました"); } 特性 functionStaticCall( ハンドル
狙い、バイト メモリ レコード、文字列 メモリ エラーメッセージ ) インナー 探検 戻り値 (バイト メモリー) { require(isContract(目的), "処理: 非契約への静的呼び出し"); (bool 成功、bytes メモリ リターンデータ)=狙い.staticcall(レコード) ; return verifyCallResult(success, returndata, errorMessage); } 特性 functionDelegateCall(ハンドル 狙い、バイト メモリ レコード) インナー 戻り値 (バイト )メモリー) { return functionDelegateCall(aim, records, " 対処:下段デリゲートの呼び出しに失敗しました"); } 特性 functionDelegateCall( ハンドル 狙い、バイト メモリ レコード、文字列 メモリ エラーメッセージ ) インナー 戻り値 (バイト メモリー) { require(isContract(目的), )"対処: 非コントラクトへのデリゲート呼び出し"); (bool 成功、bytes メモリ リターンデータ)=狙い.delegatecall(記録) ; return verifyCallResult(success, returndata, errorMessage); } 特性 verifyCallResult( bool 成功、 バイト メモリ 戻りデータ、文字列 メモリ エラーメッセージ ) インナー ピュア 戻り値 (バイト メモリー) { if (成功) { return returndata; }else { if (returndata.測定値> 0) { アセンブリ { letreturndata_size := mload(戻りデータ) 元に戻す(add(32 ), returndata), returndata_size) } } else { )revert(エラーメッセージ); } } } }
所有.solpragma solidity ^0.8.0; 契約 所有 { ハンドル 公開 所有者; ハンドル パブリック 指名所有者; コンストラクタ(ハンドル _所有者) { require(_owner !=ハンドル(0
), "所有者ハンドルを 0 にすることはできません"); 所有者=_所有者; emit OwnerChanged(handle[2 * i + 3] (0), _所有者); } 特性 nominateNewOwner(ハンドル _オーナー) 外装 オーナーのみ { 指名所有者=_オーナー; emit OwnerNominated(_owner); } 特性 所有権を受け入れる() 外観 { 必須(メッセージ.送信者== 指名された所有者, 「可能性はあります.所有権を受け入れる前に指名された」); emit OwnerChanged(所有者、指名所有者); 所有者=指名所有者; 指名所有者=ハンドル (0); } 修飾子 onlyOwner { _onlyOwner();
_; } 特性 _onlyOwner() 最深部 探検 { 必須(msg.送信者==所有者、「契約所有者のみがこのアクションを設計することもできます」); } トーナメント オーナー指名(ハンドル 新しい所有者); トーナメント OwnerChanged(ハンドル oldOwner、handle newOwner ); }
ReentrancyGuard.sol pragma 堅牢性 ^0.8.0; まとめ コントラクト ReentrancyGuard { uint256 最も深い 定数 _NOT_ENTERED=1; uint256 最も深い 定数 _ENTERED=2; uint256 最も深い _スターテス; コンストラクタ() { _status=_入力されていません; } 修飾子 再入不可() { require(_status !=_ENTERED, "ReentrancyGuard: 再入可能呼び出し"); _status=_ENTERED;_; _status=_NOT_ENTERED; } }SafeERC20.sol ) プラグマ 堅牢性 ^0.8.0; 輸入 "../interfaces/IERC20.sol"; import "./Deal with.sol"; 図書館 SafeERC20 { 活用中 対処する ために 取り持つ; 特性 safeTransfer( IERC20トークン、ハンドル に、uint256 値 ) インナー ) { _callOptionalReturn(トークン, abi.encodeWithSelector(トークン.[2 * i + 3] 転送.セレクター )、 貴ぶ)); } 特性 safeTransferFrom( IERC20トークン、ハンドル from, handle に、uint256 値 ) inner { _callOptionalReturn(トークン, abi.encodeWithSelector( token.transferFrom.selector, from、 貴ぶ)); } 特性 safeApprove( IERC20トークン、ハンドル 支出者、uint256 値 ) インナー { 必須( (値==0) || (token.allowance(ハンドル( this), 支出者)== 0 ), "SafeERC20: ゼロ以外からゼロ以外の許容範囲を承認" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)) ; } 特性 safeIncreaseAllowance( IERC20トークン、ハンドル 支出者、uint256 値 ) インナー { uint256 newAllowance=token.allowance( これを対応して) 、支出者) + 値; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)) ; } 特性 safeDecreaseAllowance( IERC20 トークン、ハンドル 支出者、uint256 値 ) インナー { チェックなし { uint256 oldAllowance=token.allowance(handle( これ)、浪費者); require(旧手当>=値、"SafeERC20: 許容値がゼロ以下に減少"); uint256 newAllowance= oldAllowance - 値; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)) ; } } 特性 _callOptionalReturn(IERC20トークン、バイト メモリ レコード) 最深部 ) { バイト メモリ リターンデータ=handle(トークン).functionCall(レコード, "SafeERC20: 低段階の呼び出しに失敗しました"); if (returndata.測定> 0) { 必須(アビ.デコード (returndata, (bool)), "SafeERC20: ERC20 の操作は成功しませんでした"); } } }
%%item_read_more_button% %