@@ -279,34 +279,49 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
279279 }
280280
281281 /// @inheritdoc IGeneralDistributionAgreementV1
282- function updateMemberUnits (ISuperfluidPool pool , address memberAddress , uint128 newUnits , bytes calldata ctx )
282+ function updateMemberUnits (
283+ ISuperfluidPool untrustedPool ,
284+ address memberAddress ,
285+ uint128 newUnits ,
286+ bytes calldata ctx
287+ )
283288 external
284289 override
285290 returns (bytes memory newCtx )
286291 {
292+ ISuperfluidToken token = untrustedPool.superToken ();
293+ address msgSender = AgreementLibrary.authorizeTokenAccess (token, ctx).msgSender;
294+
287295 // Only the admin can update member units here
288- if (AgreementLibrary. authorizeTokenAccess (pool. superToken (), ctx). msgSender != pool .admin ()) {
296+ if (msgSender != untrustedPool .admin ()) {
289297 revert GDA_NOT_POOL_ADMIN ();
290298 }
291299 newCtx = ctx;
292300
293- pool.updateMemberUnits (memberAddress, newUnits);
301+ // NOTE: In GDA.appendIndexUpdateByPool, it checks whether pool is created by the token.
302+ untrustedPool.updateMemberUnits (memberAddress, newUnits);
294303 }
295304
296305 /// @inheritdoc IGeneralDistributionAgreementV1
297- function claimAll (ISuperfluidPool pool , address memberAddress , bytes calldata ctx )
306+ function claimAll (ISuperfluidPool untrustedPool , address memberAddress , bytes calldata ctx )
298307 external
299308 override
300309 returns (bytes memory newCtx )
301310 {
302- AgreementLibrary.authorizeTokenAccess (pool.superToken (), ctx);
311+ ISuperfluidToken token = untrustedPool.superToken ();
312+ AgreementLibrary.authorizeTokenAccess (token, ctx);
303313 newCtx = ctx;
304314
305- pool.claimAll (memberAddress);
315+ // NOTE: In GDA.poolSettleClaim, it checks whether pool is created by the token.
316+ untrustedPool.claimAll (memberAddress);
306317 }
307318
308319 /// @inheritdoc IGeneralDistributionAgreementV1
309- function connectPool (ISuperfluidPool pool , bytes calldata ctx ) external override returns (bytes memory newCtx ) {
320+ function connectPool (ISuperfluidPool pool , bytes calldata ctx )
321+ external
322+ override
323+ returns (bytes memory newCtx )
324+ {
310325 newCtx = ctx;
311326 _setPoolConnectionFor (pool, address (0 ), true /* doConnect */ , ctx);
312327 }
@@ -319,6 +334,7 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
319334 {
320335 newCtx = ctx;
321336
337+ // NOTE: We do not allow a pool to connect to another pool.
322338 if (memberAddr == address (0 ) || pool.superToken ().isPool (this , memberAddr)) {
323339 revert GDA_CANNOT_CONNECT_POOL ();
324340 }
@@ -358,6 +374,10 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
358374 returns (bool success )
359375 {
360376 ISuperfluidToken token = pool.superToken ();
377+ // TODO: convert to modifier `poolIsTrustedByItsSuperToken(pool)`
378+ if (! token.isPool (this , address (pool))) {
379+ revert GDA_ONLY_SUPER_TOKEN_POOL ();
380+ }
361381 ISuperfluid.Context memory currentContext = AgreementLibrary.authorizeTokenAccess (token, ctx);
362382
363383 bool autoConnectForOtherMember = false ;
@@ -401,14 +421,22 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
401421 )
402422 );
403423
424+ // NOTE: similar to Transfer, we cannot tell if it is done through tryConnect or regular connect.
404425 emit PoolConnectionUpdated (token, pool, memberAddr, doConnect, currentContext.userData);
405426 }
406427
407428 return true ;
408429 }
409430
410431 /// @inheritdoc IGeneralDistributionAgreementV1
411- function isMemberConnected (ISuperfluidPool pool , address member ) external view override returns (bool ) {
432+ function isMemberConnected (ISuperfluidPool pool , address member )
433+ external view override
434+ returns (bool )
435+ {
436+ // NOTE: this function is total, in that even for invalid pools, it will always return false.
437+ //
438+ // Retrospectively, it may be more helpful to the developers if this function is non-total, and always revert
439+ // on invalid pool.
412440 return pool.superToken ().isPoolMemberConnected (this , pool, member);
413441 }
414442
@@ -424,9 +452,12 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
424452
425453 newCtx = ctx;
426454
427- if (token.isPool (this , address (pool)) == false ||
455+ // TODO: convert to modifier `poolIsTrustedByItsSuperToken(pool)`
456+ if (
457+ token.isPool (this , address (pool)) == false ||
428458 // Note: we do not support multi-tokens pools
429- pool.superToken () != token) {
459+ pool.superToken () != token)
460+ {
430461 revert GDA_ONLY_SUPER_TOKEN_POOL ();
431462 }
432463
@@ -490,9 +521,12 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
490521 int96 requestedFlowRate ,
491522 bytes calldata ctx
492523 ) external override returns (bytes memory newCtx ) {
493- if (token.isPool (this , address (pool)) == false ||
524+ // TODO: convert to modifier `poolIsTrustedByItsSuperToken(pool)`
525+ if (
526+ token.isPool (this , address (pool)) == false ||
494527 // Note: we do not support multi-tokens pools
495- pool.superToken () != token) {
528+ pool.superToken () != token)
529+ {
496530 revert GDA_ONLY_SUPER_TOKEN_POOL ();
497531 }
498532 if (requestedFlowRate < 0 ) {
@@ -599,6 +633,8 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
599633 )
600634 internal
601635 {
636+ // NOTE: the caller to guarantee that the token and pool are mutually trusted.
637+
602638 // not using oldFlowRate in this model
603639 // surprising effect: reducing flow rate may require more buffer when liquidation_period adjusted upward
604640 ISuperfluidGovernance gov = ISuperfluidGovernance (ISuperfluid (_host).getGovernance ());
@@ -774,39 +810,51 @@ contract GeneralDistributionAgreementV1 is AgreementBase, TokenMonad, IGeneralDi
774810
775811 //
776812 // Pool-only operations
777- //
813+ // Can only be called (`msg.sender`) by legitimate pool contracts.
814+ // If `token` is legitimate, `token.isPool()` can return true only if the pool was created by this agreement.
815+ // "false positives" (does not revert for illegitimate caller) could occur if `token`:
816+ // 1. is lying (claims the pool was registered by this agreement when it was not)
817+ // or
818+ // 2. is not associated to the same host (and agreements).
819+ // In both cases, pre-conditions are not met and no state this agreement is responsible for can be manipulated.
778820
779821 function appendIndexUpdateByPool (ISuperfluidToken token , BasicParticle memory p , Time t )
780822 external
781823 returns (bool )
782824 {
783- if (token.isPool (this , msg .sender ) == false ) {
825+ address poolAddress = msg .sender ;
826+
827+ // TODO: convert to modifier `poolIsTrustedByItsSuperToken(pool)`
828+ if (
829+ token.isPool (this , msg .sender ) == false ||
830+ ISuperfluidPool (poolAddress).superToken () != token
831+ ) {
784832 revert GDA_ONLY_SUPER_TOKEN_POOL ();
785833 }
834+
786835 bytes memory eff = abi.encode (token);
787- _setUIndex (eff, msg .sender , _getUIndex (eff, msg . sender ).mappend (p));
788- _setPoolAdjustmentFlowRate (eff, msg . sender , true , /* doShift? */ p.flow_rate (), t);
836+ _setUIndex (eff, msg .sender , _getUIndex (eff, poolAddress ).mappend (p));
837+ _setPoolAdjustmentFlowRate (eff, poolAddress , true , /* doShift? */ p.flow_rate (), t);
789838 return true ;
790839 }
791840
792- function poolSettleClaim (ISuperfluidToken superToken , address claimRecipient , int256 amount )
841+ // succeeds only if `msg.sender` is a pool trusted by `token`
842+ function poolSettleClaim (ISuperfluidToken token , address claimRecipient , int256 amount )
793843 external
794844 returns (bool )
795845 {
796- if (superToken.isPool (this , msg .sender ) == false ) {
797- revert GDA_ONLY_SUPER_TOKEN_POOL ();
798- }
846+ address poolAddress = msg .sender ;
799847
800- _doShift (abi.encode (superToken), msg .sender , claimRecipient, Value.wrap (amount));
801- return true ;
802- }
803-
804- function tokenEmitPseudoTransfer (ISuperfluidToken superToken , address from , address to ) external {
805- if (superToken.isPool (this , msg .sender ) == false ) {
848+ // TODO: convert to modifier `poolIsTrustedByItsSuperToken(pool)`
849+ if (
850+ token.isPool (this , msg .sender ) == false ||
851+ ISuperfluidPool (poolAddress).superToken () != token
852+ ) {
806853 revert GDA_ONLY_SUPER_TOKEN_POOL ();
807854 }
808855
809- superToken.emitPseudoTransfer (from, to);
856+ _doShift (abi.encode (token), poolAddress, claimRecipient, Value.wrap (amount));
857+ return true ;
810858 }
811859
812860 //////////////////////////////////////////////////////////////////////////////////////////////////////
0 commit comments