[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-12-gogeup-huff-jeogeunghyeong-silhaeng-onchein-gyesan":3},{"article":4,"author":59},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":7,"meta_description":16,"focus_keyword":17,"og_image":18,"canonical_url":18,"robots_meta":19,"created_at":15,"updated_at":15,"tags":20,"category_name":38,"related_articles":39},"d5000000-0000-0000-0000-000000000112","a0000000-0000-0000-0000-000000000052","Deep EVM #12: 고급 Huff — 적응형 실행과 온체인 계산","deep-evm-12-gogeup-huff-jeogeunghyeong-silhaeng-onchein-gyesan","실제 MEV 컨트랙트에서 추출한 프로덕션 Huff 패턴: 온체인 잔액 폴백을 사용한 적응형 실행, 우선 수수료 엔트로피를 통한 다중 운영자 인증, USDT 안전 승인, 메모리 레이아웃 트릭.","## Hello World를 넘어서\n\n이전 기사들은 Huff 기초 — 매크로, 스택 관리, 점프 테이블 — 를 다루었습니다. 이제 실제 MEV 봇 컨트랙트에서 추출한 프로덕션 패턴으로 이동합니다. 이 패턴들은 Solidity가 효율적으로 표현할 수 없는 문제를 해결합니다: 콜데이터 기반 적응형 실행, 스토리지 읽기 없는 다중 운영자 인증, 바이트코드 크기를 최소화하는 메모리 레이아웃.\n\n## 패턴 1: 적응형 실행 — `amount_in == 0` 폴백\n\nMEV 차익거래 컨트랙트에서 봇은 최적의 입력 금액을 오프체인에서 사전 계산하여 콜데이터를 통해 전달합니다. 그러나 때때로 봇은 사용 가능한 정확한 잔액을 알지 못합니다 — 예를 들어, 같은 번들의 이전 스왑이 컨트랙트에 토큰을 입금하고 정확한 출력 금액이 실행 시점의 풀 상태에 따라 달라지는 경우.\n\n해결책: 콜데이터에서 `amount_in == 0`이면, 컨트랙트가 자체 온체인 잔액을 읽어 대신 사용합니다.\n\n```huff\n#define macro GET_AMOUNT_IN() = takes(0) returns(1) {\n    \u002F\u002F 콜데이터[1..33]에서 금액 읽기\n    0x01 calldataload           \u002F\u002F [amount_in]\n    dup1                        \u002F\u002F [amount_in, amount_in]\n    use_calldata_amount jumpi   \u002F\u002F [amount_in]\n\n    \u002F\u002F amount_in == 0 → 온체인 잔액 읽기\n    pop                         \u002F\u002F []\n\n    \u002F\u002F balanceOf(address(this)) 호출 구성\n    \u002F\u002F selector: 0x70a08231\n    0x70a08231                  \u002F\u002F [selector]\n    0xe0 shl                    \u002F\u002F [selector \u003C\u003C 224]\n    0x00 mstore                 \u002F\u002F [] — memory[0x00] = selector\n    address                     \u002F\u002F [this]\n    0x04 mstore                 \u002F\u002F [] — memory[0x04] = address(this)\n\n    \u002F\u002F 토큰에 staticcall\n    0x20                        \u002F\u002F [retSize]\n    0x00                        \u002F\u002F [retOffset]\n    0x24                        \u002F\u002F [argSize]\n    0x00                        \u002F\u002F [argOffset]\n    [TOKEN]                     \u002F\u002F [token, argOffset, argSize, retOffset, retSize]\n    gas                         \u002F\u002F [gas, token, ...]\n    staticcall                  \u002F\u002F [success]\n    pop                         \u002F\u002F []\n    0x00 mload                  \u002F\u002F [balance] — 실제 토큰 잔액\n    \u002F\u002F amount_in으로 사용하기 위해 이어짐\n\n    use_calldata_amount:\n    \u002F\u002F 스택: [amount_in] (콜데이터 또는 balanceOf에서)\n}\n```\n\n이 패턴은 폴백이 트리거될 때 약 200 가스를 추가하지만(staticcall), amount_in이 콜데이터에 제공될 때는 제로 가스입니다(DUP + JUMPI만). 봇은 90%의 경우 콜데이터 경로를 사용하고 중간 금액이 예측 불가능한 다단계 번들을 실행할 때만 온체인 읽기로 폴백합니다.\n\n## 패턴 2: 우선 수수료 엔트로피를 통한 다중 운영자 인증\n\nMEV 봇은 종종 컨트랙트를 호출할 수 있는 여러 운영자(핫 월렛)가 필요합니다. 매핑에 승인된 주소를 저장하면 SLOAD당 2,100 가스(cold) 또는 100 가스(warm)가 듭니다. 블록당 한 번 호출되는 컨트랙트의 경우 모든 호출이 cold입니다.\n\n대안: 트랜잭션의 `tx.gasprice`(더 정확히는 우선 수수료)에 운영자의 인증을 인코딩합니다. 봇이 비밀 논스를 포함하는 값으로 `maxPriorityFeePerGas`를 설정합니다:\n\n```huff\n#define constant AUTH_MASK = 0xFFFF  \u002F\u002F 우선 수수료의 하위 16비트\n#define constant AUTH_SECRET = 0xBEEF\n\n#define macro CHECK_AUTH() = takes(0) returns(0) {\n    \u002F\u002F 우선 수수료 추출: gasprice - basefee\n    gasprice            \u002F\u002F [gasprice]\n    basefee             \u002F\u002F [basefee, gasprice]\n    swap1 sub           \u002F\u002F [priority_fee]\n\n    \u002F\u002F 하위 16비트가 비밀과 일치하는지 확인\n    [AUTH_MASK]         \u002F\u002F [mask, priority_fee]\n    and                 \u002F\u002F [fee & mask]\n    [AUTH_SECRET]       \u002F\u002F [secret, fee & mask]\n    eq                  \u002F\u002F [authorized?]\n    authorized jumpi\n    0x00 0x00 revert\n\n    authorized:\n}\n```\n\n이것은 스토리지 기반 접근법의 2,100+ 대비 14 가스만 듭니다(GASPRICE + BASEFEE + SUB + AND + EQ + JUMPI). 트레이드오프: 비밀이 멤풀에서 보입니다. 그러나 MEV 봇은 Flashbots나 프라이빗 멤풀을 사용하므로 트랜잭션은 포함 전에 공개적으로 보이지 않습니다.\n\n우선 수수료 비트를 분할하여 다른 운영자에 대해 다른 비밀을 인코딩할 수 있습니다 — 예: 비트 0-15는 인증 토큰, 비트 16-31은 운영자 ID.\n\n## 패턴 3: USDT 안전 승인 (제로 리셋)\n\nUSDT의 `approve` 함수는 현재 허용량이 0이 아니고 새로운 0이 아닌 값을 설정하려 하면 되돌립니다. 이것은 수많은 DeFi 통합을 깨뜨린 악명 높은 quirk입니다. Huff에서는 항상 먼저 0으로 리셋하여 처리합니다:\n\n```huff\n#define macro SAFE_APPROVE() = takes(2) returns(0) {\n    \u002F\u002F takes: [spender, amount]\n\n    \u002F\u002F 먼저: approve(spender, 0)\n    0x095ea7b3 0xe0 shl     \u002F\u002F [approve_selector]\n    0x00 mstore             \u002F\u002F memory[0x00] = selector\n    dup2                    \u002F\u002F [spender, spender, amount]\n    0x04 mstore             \u002F\u002F memory[0x04] = spender  [spender, amount]\n    0x00 0x24 mstore        \u002F\u002F memory[0x24] = 0        [spender, amount]\n\n    0x00                    \u002F\u002F [retSize]\n    0x00                    \u002F\u002F [retOffset]\n    0x44                    \u002F\u002F [argSize]\n    0x00                    \u002F\u002F [argOffset]\n    0x00                    \u002F\u002F [value (ETH 없음)]\n    [USDT]                  \u002F\u002F [token]\n    gas call                \u002F\u002F [success]\n    pop                     \u002F\u002F [] — 결과 무시, 일부 토큰은 아무것도 반환하지 않음\n\n    \u002F\u002F 두 번째: approve(spender, amount)\n    \u002F\u002F selector는 여전히 memory[0x00]에\n    \u002F\u002F spender는 여전히 memory[0x04]에\n    swap1                   \u002F\u002F [amount, spender]\n    0x24 mstore             \u002F\u002F memory[0x24] = amount  [spender]\n    pop                     \u002F\u002F []\n\n    0x00 0x00 0x44 0x00 0x00\n    [USDT] gas call\n    pop\n}\n```\n\n이 패턴은 USDT뿐만 아니라 모든 ERC20 토큰에 대해 작동합니다 — 안전한 범용 승인입니다. 추가 호출은 약 2,600 가스(warm CALL)이지만 조용한 실패를 방지합니다.\n\n## 패턴 4: WETH 입금 및 출금\n\nWETH (Wrapped Ether) 변환은 MEV 봇에서 빈번한 작업입니다. ABI는 간단합니다:\n\n```huff\n#define constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\n\n#define macro WETH_DEPOSIT() = takes(1) returns(0) {\n    \u002F\u002F takes: [amount]\n    \u002F\u002F WETH.deposit{value: amount}()\n    0x00 0x00 0x00 0x00     \u002F\u002F [0, 0, 0, 0, amount] — retSize, retOff, argSize, argOff\n    swap4                   \u002F\u002F [amount, 0, 0, 0, 0]\n    [WETH]                  \u002F\u002F [weth, amount, 0, 0, 0, 0]\n    gas call                \u002F\u002F [success]\n    pop\n}\n\n#define macro WETH_WITHDRAW() = takes(1) returns(0) {\n    \u002F\u002F takes: [amount]\n    \u002F\u002F WETH.withdraw(amount)\n    0x2e1a7d4d 0xe0 shl     \u002F\u002F [selector, amount]\n    0x00 mstore             \u002F\u002F memory[0] = selector     [amount]\n    0x04 mstore             \u002F\u002F memory[4] = amount       []\n\n    0x00 0x00 0x24 0x00 0x00\n    [WETH] gas call\n    pop\n}\n```\n\n입금 함수는 특히 우아합니다 — WETH의 deposit은 인수가 없으므로 ETH 값과 함께 제로 argSize를 보냅니다. 입금을 위한 총 바이트코드: 약 20바이트.\n\n## 메모리 레이아웃 트릭\n\nEVM 메모리는 바이트 주소 지정이 가능하고 확장이 자유롭습니다(확장에 이차적으로 가스 소비). MEV 컨트랙트는 중복 MSTORE 작업을 피하기 위해 고정 메모리 레이아웃을 사용합니다:\n\n```huff\n\u002F\u002F 고정 메모리 레이아웃 — 호출 간에 변경되지 않음\n\u002F\u002F 0x00 - 0x03:  현재 함수 셀렉터 (4바이트)\n\u002F\u002F 0x04 - 0x23:  인수 1 (32바이트)\n\u002F\u002F 0x24 - 0x43:  인수 2 (32바이트)\n\u002F\u002F 0x44 - 0x63:  인수 3 (32바이트)\n\u002F\u002F 0x64 - 0x83:  반환 데이터 스크래치 (32바이트)\n\u002F\u002F 0x80 - 0x9f:  스택 스필 영역 (32바이트)\n\u002F\u002F 0xa0 - 0xbf:  두 번째 스필 슬롯 (32바이트)\n```\n\n핵심 통찰: 같은 셀렉터로 여러 외부 호출을 하는 경우(예: 여러 `transfer` 호출), 셀렉터를 한 번만 씁니다. 후속 호출에서는 변경된 인수만 업데이트합니다.\n\n```huff\n#define macro MULTI_TRANSFER() = takes(0) returns(0) {\n    \u002F\u002F 설정: transfer 셀렉터를 한 번 작성\n    0xa9059cbb 0xe0 shl\n    0x00 mstore                 \u002F\u002F memory[0] = transfer(address,uint256)\n\n    \u002F\u002F 전송 1: to=Alice, amount=100\n    [ALICE] 0x04 mstore\n    0x64 0x24 mstore            \u002F\u002F 100\n    0x00 0x00 0x44 0x00 0x00 [TOKEN] gas call pop\n\n    \u002F\u002F 전송 2: to=Bob, amount=200\n    \u002F\u002F 셀렉터는 여전히 memory[0]에 — 다시 쓸 필요 없음!\n    [BOB] 0x04 mstore\n    0xc8 0x24 mstore            \u002F\u002F 200\n    0x00 0x00 0x44 0x00 0x00 [TOKEN] gas call pop\n\n    \u002F\u002F 전송 3: to=Bob, amount=300\n    \u002F\u002F 주소는 여전히 memory[4]에 — 금액만 업데이트!\n    0x012c 0x24 mstore          \u002F\u002F 300\n    0x00 0x00 0x44 0x00 0x00 [TOKEN] gas call pop\n}\n```\n\n피한 MSTORE마다 3 가스 + 값에 대한 PUSH를 절약합니다. 5-6번의 스왑 호출이 있는 멀티홉 차익거래에서 50-100 가스를 절약합니다.\n\n## 프리 메모리 포인터의 신화\n\nSolidity는 다음 사용 가능한 메모리 오프셋을 추적하는 \"프리 메모리 포인터\"를 `0x40`에 유지합니다. 이것은 동적 메모리 할당(배열, 문자열, abi.encode)을 위한 추상화입니다. Huff에서는 이것이 필요 없습니다.\n\nMEV 컨트랙트는 외부 호출의 고정된 알려진 집합을 가집니다. 컴파일 시간에 메모리 영역을 정적으로 할당할 수 있습니다. 프리 메모리 포인터가 없다는 것은:\n\n- 모든 메모리 쓰기 전에 포인터를 읽는 3 가스 MLOAD가 없음.\n- 모든 할당 후 포인터를 업데이트하는 3 가스 MSTORE가 없음.\n- 재진입으로 인한 메모리 충돌 위험이 없음(레이아웃이 결정적).\n\n프리 메모리 포인터를 삭제하세요. 메모리 맵을 직접 소유하세요.\n\n## 패턴 결합: 프로덕션 스왑 매크로\n\n여러 패턴을 결합한 프로덕션급 Uniswap V2 스왑 매크로입니다:\n\n```huff\n#define macro SWAP_V2() = takes(3) returns(0) {\n    \u002F\u002F takes: [amountOut, zeroForOne, pair]\n\n    \u002F\u002F swap(uint256,uint256,address,bytes) 호출 구성\n    0x022c0d9f 0xe0 shl\n    0x00 mstore                     \u002F\u002F selector\n\n    \u002F\u002F amount0Out = zeroForOne ? 0 : amountOut\n    \u002F\u002F amount1Out = zeroForOne ? amountOut : 0\n    swap1                           \u002F\u002F [zeroForOne, amountOut, pair]\n    skip_zero jumpi                 \u002F\u002F [amountOut, pair]\n\n    \u002F\u002F zeroForOne == 0: token1 → token0, amount0Out = amountOut\n    dup1 0x04 mstore                \u002F\u002F amount0Out = amountOut\n    0x00 0x24 mstore                \u002F\u002F amount1Out = 0\n    done_amounts jump\n\n    skip_zero:                      \u002F\u002F [amountOut, pair]\n    0x00 0x04 mstore                \u002F\u002F amount0Out = 0\n    dup1 0x24 mstore                \u002F\u002F amount1Out = amountOut\n\n    done_amounts:\n    pop                             \u002F\u002F [pair]\n    address 0x44 mstore             \u002F\u002F to = address(this)\n    0x80 0x64 mstore                \u002F\u002F bytes offset\n    0x00 0x84 mstore                \u002F\u002F bytes length = 0\n\n    \u002F\u002F pair.swap 호출\n    0x00 0x00 0xa4 0x00 0x00\n    swap5                           \u002F\u002F [pair, ...]\n    gas call\n\n    \u002F\u002F 성공 확인\n    iszero revert_swap jumpi\n    stop\n\n    revert_swap:\n        returndatasize 0x00 0x00 returndatacopy\n        returndatasize 0x00 revert\n}\n```\n\n이것은 120바이트의 바이트코드입니다. SafeERC20, 인터페이스 타입, ABI 인코딩이 포함된 동등한 Solidity는 400+ 바이트를 생성합니다.\n\n## 요약\n\n고급 Huff는 학술적 연습이 아닌 프로덕션 패턴에 관한 것입니다. `amount_in == 0` 폴백은 봇이 예측 불가능한 중간 상태에 적응할 수 있게 합니다. 우선 수수료 인증은 cold SLOAD 비용을 제거합니다. USDT 안전 승인은 조용한 되돌림을 방지합니다. 고정 메모리 레이아웃은 중복 쓰기를 제거합니다. 각 패턴은 50-200 가스를 절약합니다 — 그리고 MEV에서 이 절약은 수천 번의 일일 실행에 걸쳐 의미 있는 이익으로 복합됩니다. 다음 기사에서는 컨트랙트 작성에서 익스플로잇으로 초점을 전환합니다: MEV에 대한 소개 — 추출 가능한 가치, 서처, 블록 빌더.","\u003Ch2 id=\"hello-world\">Hello World를 넘어서\u003C\u002Fh2>\n\u003Cp>이전 기사들은 Huff 기초 — 매크로, 스택 관리, 점프 테이블 — 를 다루었습니다. 이제 실제 MEV 봇 컨트랙트에서 추출한 프로덕션 패턴으로 이동합니다. 이 패턴들은 Solidity가 효율적으로 표현할 수 없는 문제를 해결합니다: 콜데이터 기반 적응형 실행, 스토리지 읽기 없는 다중 운영자 인증, 바이트코드 크기를 최소화하는 메모리 레이아웃.\u003C\u002Fp>\n\u003Ch2 id=\"1-amount-in-0\">패턴 1: 적응형 실행 — \u003Ccode>amount_in == 0\u003C\u002Fcode> 폴백\u003C\u002Fh2>\n\u003Cp>MEV 차익거래 컨트랙트에서 봇은 최적의 입력 금액을 오프체인에서 사전 계산하여 콜데이터를 통해 전달합니다. 그러나 때때로 봇은 사용 가능한 정확한 잔액을 알지 못합니다 — 예를 들어, 같은 번들의 이전 스왑이 컨트랙트에 토큰을 입금하고 정확한 출력 금액이 실행 시점의 풀 상태에 따라 달라지는 경우.\u003C\u002Fp>\n\u003Cp>해결책: 콜데이터에서 \u003Ccode>amount_in == 0\u003C\u002Fcode>이면, 컨트랙트가 자체 온체인 잔액을 읽어 대신 사용합니다.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define macro GET_AMOUNT_IN() = takes(0) returns(1) {\n    \u002F\u002F 콜데이터[1..33]에서 금액 읽기\n    0x01 calldataload           \u002F\u002F [amount_in]\n    dup1                        \u002F\u002F [amount_in, amount_in]\n    use_calldata_amount jumpi   \u002F\u002F [amount_in]\n\n    \u002F\u002F amount_in == 0 → 온체인 잔액 읽기\n    pop                         \u002F\u002F []\n\n    \u002F\u002F balanceOf(address(this)) 호출 구성\n    \u002F\u002F selector: 0x70a08231\n    0x70a08231                  \u002F\u002F [selector]\n    0xe0 shl                    \u002F\u002F [selector &lt;&lt; 224]\n    0x00 mstore                 \u002F\u002F [] — memory[0x00] = selector\n    address                     \u002F\u002F [this]\n    0x04 mstore                 \u002F\u002F [] — memory[0x04] = address(this)\n\n    \u002F\u002F 토큰에 staticcall\n    0x20                        \u002F\u002F [retSize]\n    0x00                        \u002F\u002F [retOffset]\n    0x24                        \u002F\u002F [argSize]\n    0x00                        \u002F\u002F [argOffset]\n    [TOKEN]                     \u002F\u002F [token, argOffset, argSize, retOffset, retSize]\n    gas                         \u002F\u002F [gas, token, ...]\n    staticcall                  \u002F\u002F [success]\n    pop                         \u002F\u002F []\n    0x00 mload                  \u002F\u002F [balance] — 실제 토큰 잔액\n    \u002F\u002F amount_in으로 사용하기 위해 이어짐\n\n    use_calldata_amount:\n    \u002F\u002F 스택: [amount_in] (콜데이터 또는 balanceOf에서)\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>이 패턴은 폴백이 트리거될 때 약 200 가스를 추가하지만(staticcall), amount_in이 콜데이터에 제공될 때는 제로 가스입니다(DUP + JUMPI만). 봇은 90%의 경우 콜데이터 경로를 사용하고 중간 금액이 예측 불가능한 다단계 번들을 실행할 때만 온체인 읽기로 폴백합니다.\u003C\u002Fp>\n\u003Ch2 id=\"2\">패턴 2: 우선 수수료 엔트로피를 통한 다중 운영자 인증\u003C\u002Fh2>\n\u003Cp>MEV 봇은 종종 컨트랙트를 호출할 수 있는 여러 운영자(핫 월렛)가 필요합니다. 매핑에 승인된 주소를 저장하면 SLOAD당 2,100 가스(cold) 또는 100 가스(warm)가 듭니다. 블록당 한 번 호출되는 컨트랙트의 경우 모든 호출이 cold입니다.\u003C\u002Fp>\n\u003Cp>대안: 트랜잭션의 \u003Ccode>tx.gasprice\u003C\u002Fcode>(더 정확히는 우선 수수료)에 운영자의 인증을 인코딩합니다. 봇이 비밀 논스를 포함하는 값으로 \u003Ccode>maxPriorityFeePerGas\u003C\u002Fcode>를 설정합니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define constant AUTH_MASK = 0xFFFF  \u002F\u002F 우선 수수료의 하위 16비트\n#define constant AUTH_SECRET = 0xBEEF\n\n#define macro CHECK_AUTH() = takes(0) returns(0) {\n    \u002F\u002F 우선 수수료 추출: gasprice - basefee\n    gasprice            \u002F\u002F [gasprice]\n    basefee             \u002F\u002F [basefee, gasprice]\n    swap1 sub           \u002F\u002F [priority_fee]\n\n    \u002F\u002F 하위 16비트가 비밀과 일치하는지 확인\n    [AUTH_MASK]         \u002F\u002F [mask, priority_fee]\n    and                 \u002F\u002F [fee &amp; mask]\n    [AUTH_SECRET]       \u002F\u002F [secret, fee &amp; mask]\n    eq                  \u002F\u002F [authorized?]\n    authorized jumpi\n    0x00 0x00 revert\n\n    authorized:\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>이것은 스토리지 기반 접근법의 2,100+ 대비 14 가스만 듭니다(GASPRICE + BASEFEE + SUB + AND + EQ + JUMPI). 트레이드오프: 비밀이 멤풀에서 보입니다. 그러나 MEV 봇은 Flashbots나 프라이빗 멤풀을 사용하므로 트랜잭션은 포함 전에 공개적으로 보이지 않습니다.\u003C\u002Fp>\n\u003Cp>우선 수수료 비트를 분할하여 다른 운영자에 대해 다른 비밀을 인코딩할 수 있습니다 — 예: 비트 0-15는 인증 토큰, 비트 16-31은 운영자 ID.\u003C\u002Fp>\n\u003Ch2 id=\"3-usdt\">패턴 3: USDT 안전 승인 (제로 리셋)\u003C\u002Fh2>\n\u003Cp>USDT의 \u003Ccode>approve\u003C\u002Fcode> 함수는 현재 허용량이 0이 아니고 새로운 0이 아닌 값을 설정하려 하면 되돌립니다. 이것은 수많은 DeFi 통합을 깨뜨린 악명 높은 quirk입니다. Huff에서는 항상 먼저 0으로 리셋하여 처리합니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define macro SAFE_APPROVE() = takes(2) returns(0) {\n    \u002F\u002F takes: [spender, amount]\n\n    \u002F\u002F 먼저: approve(spender, 0)\n    0x095ea7b3 0xe0 shl     \u002F\u002F [approve_selector]\n    0x00 mstore             \u002F\u002F memory[0x00] = selector\n    dup2                    \u002F\u002F [spender, spender, amount]\n    0x04 mstore             \u002F\u002F memory[0x04] = spender  [spender, amount]\n    0x00 0x24 mstore        \u002F\u002F memory[0x24] = 0        [spender, amount]\n\n    0x00                    \u002F\u002F [retSize]\n    0x00                    \u002F\u002F [retOffset]\n    0x44                    \u002F\u002F [argSize]\n    0x00                    \u002F\u002F [argOffset]\n    0x00                    \u002F\u002F [value (ETH 없음)]\n    [USDT]                  \u002F\u002F [token]\n    gas call                \u002F\u002F [success]\n    pop                     \u002F\u002F [] — 결과 무시, 일부 토큰은 아무것도 반환하지 않음\n\n    \u002F\u002F 두 번째: approve(spender, amount)\n    \u002F\u002F selector는 여전히 memory[0x00]에\n    \u002F\u002F spender는 여전히 memory[0x04]에\n    swap1                   \u002F\u002F [amount, spender]\n    0x24 mstore             \u002F\u002F memory[0x24] = amount  [spender]\n    pop                     \u002F\u002F []\n\n    0x00 0x00 0x44 0x00 0x00\n    [USDT] gas call\n    pop\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>이 패턴은 USDT뿐만 아니라 모든 ERC20 토큰에 대해 작동합니다 — 안전한 범용 승인입니다. 추가 호출은 약 2,600 가스(warm CALL)이지만 조용한 실패를 방지합니다.\u003C\u002Fp>\n\u003Ch2 id=\"4-weth\">패턴 4: WETH 입금 및 출금\u003C\u002Fh2>\n\u003Cp>WETH (Wrapped Ether) 변환은 MEV 봇에서 빈번한 작업입니다. ABI는 간단합니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\n\n#define macro WETH_DEPOSIT() = takes(1) returns(0) {\n    \u002F\u002F takes: [amount]\n    \u002F\u002F WETH.deposit{value: amount}()\n    0x00 0x00 0x00 0x00     \u002F\u002F [0, 0, 0, 0, amount] — retSize, retOff, argSize, argOff\n    swap4                   \u002F\u002F [amount, 0, 0, 0, 0]\n    [WETH]                  \u002F\u002F [weth, amount, 0, 0, 0, 0]\n    gas call                \u002F\u002F [success]\n    pop\n}\n\n#define macro WETH_WITHDRAW() = takes(1) returns(0) {\n    \u002F\u002F takes: [amount]\n    \u002F\u002F WETH.withdraw(amount)\n    0x2e1a7d4d 0xe0 shl     \u002F\u002F [selector, amount]\n    0x00 mstore             \u002F\u002F memory[0] = selector     [amount]\n    0x04 mstore             \u002F\u002F memory[4] = amount       []\n\n    0x00 0x00 0x24 0x00 0x00\n    [WETH] gas call\n    pop\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>입금 함수는 특히 우아합니다 — WETH의 deposit은 인수가 없으므로 ETH 값과 함께 제로 argSize를 보냅니다. 입금을 위한 총 바이트코드: 약 20바이트.\u003C\u002Fp>\n\u003Ch2 id=\"\">메모리 레이아웃 트릭\u003C\u002Fh2>\n\u003Cp>EVM 메모리는 바이트 주소 지정이 가능하고 확장이 자유롭습니다(확장에 이차적으로 가스 소비). MEV 컨트랙트는 중복 MSTORE 작업을 피하기 위해 고정 메모리 레이아웃을 사용합니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">\u002F\u002F 고정 메모리 레이아웃 — 호출 간에 변경되지 않음\n\u002F\u002F 0x00 - 0x03:  현재 함수 셀렉터 (4바이트)\n\u002F\u002F 0x04 - 0x23:  인수 1 (32바이트)\n\u002F\u002F 0x24 - 0x43:  인수 2 (32바이트)\n\u002F\u002F 0x44 - 0x63:  인수 3 (32바이트)\n\u002F\u002F 0x64 - 0x83:  반환 데이터 스크래치 (32바이트)\n\u002F\u002F 0x80 - 0x9f:  스택 스필 영역 (32바이트)\n\u002F\u002F 0xa0 - 0xbf:  두 번째 스필 슬롯 (32바이트)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>핵심 통찰: 같은 셀렉터로 여러 외부 호출을 하는 경우(예: 여러 \u003Ccode>transfer\u003C\u002Fcode> 호출), 셀렉터를 한 번만 씁니다. 후속 호출에서는 변경된 인수만 업데이트합니다.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define macro MULTI_TRANSFER() = takes(0) returns(0) {\n    \u002F\u002F 설정: transfer 셀렉터를 한 번 작성\n    0xa9059cbb 0xe0 shl\n    0x00 mstore                 \u002F\u002F memory[0] = transfer(address,uint256)\n\n    \u002F\u002F 전송 1: to=Alice, amount=100\n    [ALICE] 0x04 mstore\n    0x64 0x24 mstore            \u002F\u002F 100\n    0x00 0x00 0x44 0x00 0x00 [TOKEN] gas call pop\n\n    \u002F\u002F 전송 2: to=Bob, amount=200\n    \u002F\u002F 셀렉터는 여전히 memory[0]에 — 다시 쓸 필요 없음!\n    [BOB] 0x04 mstore\n    0xc8 0x24 mstore            \u002F\u002F 200\n    0x00 0x00 0x44 0x00 0x00 [TOKEN] gas call pop\n\n    \u002F\u002F 전송 3: to=Bob, amount=300\n    \u002F\u002F 주소는 여전히 memory[4]에 — 금액만 업데이트!\n    0x012c 0x24 mstore          \u002F\u002F 300\n    0x00 0x00 0x44 0x00 0x00 [TOKEN] gas call pop\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>피한 MSTORE마다 3 가스 + 값에 대한 PUSH를 절약합니다. 5-6번의 스왑 호출이 있는 멀티홉 차익거래에서 50-100 가스를 절약합니다.\u003C\u002Fp>\n\u003Ch2 id=\"\">프리 메모리 포인터의 신화\u003C\u002Fh2>\n\u003Cp>Solidity는 다음 사용 가능한 메모리 오프셋을 추적하는 “프리 메모리 포인터“를 \u003Ccode>0x40\u003C\u002Fcode>에 유지합니다. 이것은 동적 메모리 할당(배열, 문자열, abi.encode)을 위한 추상화입니다. Huff에서는 이것이 필요 없습니다.\u003C\u002Fp>\n\u003Cp>MEV 컨트랙트는 외부 호출의 고정된 알려진 집합을 가집니다. 컴파일 시간에 메모리 영역을 정적으로 할당할 수 있습니다. 프리 메모리 포인터가 없다는 것은:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>모든 메모리 쓰기 전에 포인터를 읽는 3 가스 MLOAD가 없음.\u003C\u002Fli>\n\u003Cli>모든 할당 후 포인터를 업데이트하는 3 가스 MSTORE가 없음.\u003C\u002Fli>\n\u003Cli>재진입으로 인한 메모리 충돌 위험이 없음(레이아웃이 결정적).\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>프리 메모리 포인터를 삭제하세요. 메모리 맵을 직접 소유하세요.\u003C\u002Fp>\n\u003Ch2 id=\"\">패턴 결합: 프로덕션 스왑 매크로\u003C\u002Fh2>\n\u003Cp>여러 패턴을 결합한 프로덕션급 Uniswap V2 스왑 매크로입니다:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-huff\">#define macro SWAP_V2() = takes(3) returns(0) {\n    \u002F\u002F takes: [amountOut, zeroForOne, pair]\n\n    \u002F\u002F swap(uint256,uint256,address,bytes) 호출 구성\n    0x022c0d9f 0xe0 shl\n    0x00 mstore                     \u002F\u002F selector\n\n    \u002F\u002F amount0Out = zeroForOne ? 0 : amountOut\n    \u002F\u002F amount1Out = zeroForOne ? amountOut : 0\n    swap1                           \u002F\u002F [zeroForOne, amountOut, pair]\n    skip_zero jumpi                 \u002F\u002F [amountOut, pair]\n\n    \u002F\u002F zeroForOne == 0: token1 → token0, amount0Out = amountOut\n    dup1 0x04 mstore                \u002F\u002F amount0Out = amountOut\n    0x00 0x24 mstore                \u002F\u002F amount1Out = 0\n    done_amounts jump\n\n    skip_zero:                      \u002F\u002F [amountOut, pair]\n    0x00 0x04 mstore                \u002F\u002F amount0Out = 0\n    dup1 0x24 mstore                \u002F\u002F amount1Out = amountOut\n\n    done_amounts:\n    pop                             \u002F\u002F [pair]\n    address 0x44 mstore             \u002F\u002F to = address(this)\n    0x80 0x64 mstore                \u002F\u002F bytes offset\n    0x00 0x84 mstore                \u002F\u002F bytes length = 0\n\n    \u002F\u002F pair.swap 호출\n    0x00 0x00 0xa4 0x00 0x00\n    swap5                           \u002F\u002F [pair, ...]\n    gas call\n\n    \u002F\u002F 성공 확인\n    iszero revert_swap jumpi\n    stop\n\n    revert_swap:\n        returndatasize 0x00 0x00 returndatacopy\n        returndatasize 0x00 revert\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>이것은 120바이트의 바이트코드입니다. SafeERC20, 인터페이스 타입, ABI 인코딩이 포함된 동등한 Solidity는 400+ 바이트를 생성합니다.\u003C\u002Fp>\n\u003Ch2 id=\"\">요약\u003C\u002Fh2>\n\u003Cp>고급 Huff는 학술적 연습이 아닌 프로덕션 패턴에 관한 것입니다. \u003Ccode>amount_in == 0\u003C\u002Fcode> 폴백은 봇이 예측 불가능한 중간 상태에 적응할 수 있게 합니다. 우선 수수료 인증은 cold SLOAD 비용을 제거합니다. USDT 안전 승인은 조용한 되돌림을 방지합니다. 고정 메모리 레이아웃은 중복 쓰기를 제거합니다. 각 패턴은 50-200 가스를 절약합니다 — 그리고 MEV에서 이 절약은 수천 번의 일일 실행에 걸쳐 의미 있는 이익으로 복합됩니다. 다음 기사에서는 컨트랙트 작성에서 익스플로잇으로 초점을 전환합니다: MEV에 대한 소개 — 추출 가능한 가치, 서처, 블록 빌더.\u003C\u002Fp>\n","ko","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:28.034Z","MEV 컨트랙트를 위한 프로덕션 Huff 패턴: 온체인 잔액 폴백, 우선 수수료 인증, USDT 안전 승인, WETH 처리, 메모리 레이아웃 트릭.","고급 huff mev 패턴",null,"index, follow",[21,26,30,34],{"id":22,"name":23,"slug":24,"created_at":25},"c0000000-0000-0000-0000-000000000016","EVM","evm","2026-03-28T10:44:21.513630Z",{"id":27,"name":28,"slug":29,"created_at":25},"c0000000-0000-0000-0000-000000000017","Huff","huff",{"id":31,"name":32,"slug":33,"created_at":25},"c0000000-0000-0000-0000-000000000019","MEV","mev",{"id":35,"name":36,"slug":37,"created_at":25},"c0000000-0000-0000-0000-000000000013","Security","security","블록체인",[40,47,53],{"id":41,"title":42,"slug":43,"excerpt":44,"locale":12,"category_name":45,"published_at":46},"d0000000-0000-0000-0000-000000000674","2026년, Bali가 동남아시아의 임팩트 테크 허브가 되고 있는 이유","bali-2026-dongnamasia-impaekteu-tekeu-heobeu-iyu","Bali는 동남아시아 스타트업 생태계에서 16위를 차지하고 있습니다. Web3 빌더, AI 지속가능성 스타트업, 에코 여행 테크 기업이 집중되면서, 이 섬은 지역 임팩트 테크의 수도로 자리매김하고 있습니다.","엔지니어링","2026-03-28T10:44:49.294484Z",{"id":48,"title":49,"slug":50,"excerpt":51,"locale":12,"category_name":45,"published_at":52},"d0000000-0000-0000-0000-000000000673","ASEAN 데이터 보호 패치워크: 개발자를 위한 컴플라이언스 체크리스트","asean-deiteo-boho-paechiwokeu-gaebaljaleul-wihan-keompeullaieonseuchekeuriseuteu","7개 ASEAN 국가가 포괄적인 데이터 보호법을 시행하고 있으며, 각각 다른 동의 모델, 현지화 요건, 벌칙 구조를 가지고 있습니다. 다중 국가 애플리케이션을 구축하는 개발자를 위한 실용적인 컴플라이언스 체크리스트입니다.","2026-03-28T10:44:49.286400Z",{"id":54,"title":55,"slug":56,"excerpt":57,"locale":12,"category_name":45,"published_at":58},"d0000000-0000-0000-0000-000000000672","Indonesia 290억 달러 디지털 전환: 소프트웨어 기업을 위한 기회","indonesia-290eok-dallleo-dijiteol-jeonhwan-sopeuteuweo-gieopui-gihoe","Indonesia IT 서비스 시장은 2026년 290.3억 달러에 달할 것으로 예상되며, 이는 2025년 243.7억 달러에서 증가한 수치입니다. 클라우드 인프라, AI, 전자상거래, 데이터센터가 동남아시아에서 가장 빠른 성장을 주도하고 있습니다.","2026-03-28T10:44:49.265609Z",{"id":13,"name":60,"slug":61,"bio":62,"photo_url":18,"linkedin":18,"role":63,"created_at":64,"updated_at":64},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]